diff --git a/CHANGELOG.md b/CHANGELOG.md index 91b3fac110bb5..20198502e6281 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## New Features: -No changes to highlight. +- Adds a `root_path` parameter to `launch()` that allows running Gradio applications on subpaths (e.g. www.example.com/app) behind a proxy, by [@abidlabs](https://github.com/abidlabs) in [PR 4133](https://github.com/gradio-app/gradio/pull/4133) ## Bug Fixes: diff --git a/gradio/blocks.py b/gradio/blocks.py index e6c28a94b4b17..f890206882afe 100644 --- a/gradio/blocks.py +++ b/gradio/blocks.py @@ -93,7 +93,6 @@ def __init__( self._skip_init_processing = _skip_init_processing self._style = {} self.parent: BlockContext | None = None - self.root = "" if render: self.render() @@ -717,6 +716,7 @@ def __init__( self.allowed_paths = [] self.blocked_paths = [] + self.root_path = "" if self.analytics_enabled: is_custom_theme = not any( @@ -1353,7 +1353,6 @@ def get_config_file(self): "show_api": self.show_api, "is_colab": utils.colab_check(), "stylesheets": self.stylesheets, - "root": self.root, "theme": self.theme.name, } @@ -1606,6 +1605,7 @@ def launch( file_directories: list[str] | None = None, allowed_paths: list[str] | None = None, blocked_paths: list[str] | None = None, + root_path: str = "", _frontend: bool = True, ) -> tuple[FastAPI, str, str]: """ @@ -1639,6 +1639,7 @@ def launch( file_directories: This parameter has been renamed to `allowed_paths`. It will be removed in a future version. allowed_paths: List of complete filepaths or parent directories that gradio is allowed to serve (in addition to the directory containing the gradio python file). Must be absolute paths. Warning: if you provide directories, any files in these directories or their subdirectories are accessible to all users of your app. blocked_paths: List of complete filepaths or parent directories that gradio is not allowed to serve (i.e. users of your app are not allowed to access). Must be absolute paths. Warning: takes precedence over `allowed_paths` and all other directories exposed by Gradio by default. + root_path: The root path (or "mount point") of the application, if it's not served from the root ("/") of the domain. Often used when the application is behind a reverse proxy that forwards requests to the application. For example, if the application is served at "https://example.com/myapp", the `root_path` should be set to "/myapp". Returns: app: FastAPI app object that is running the demo local_url: Locally accessible link to the demo @@ -1678,6 +1679,7 @@ def reverse(text): self.width = width self.favicon_path = favicon_path self.ssl_verify = ssl_verify + self.root_path = root_path if enable_queue is not None: self.enable_queue = enable_queue diff --git a/gradio/routes.py b/gradio/routes.py index e275d5ae2c60b..49fcc6e282a4a 100644 --- a/gradio/routes.py +++ b/gradio/routes.py @@ -133,6 +133,7 @@ def configure_app(self, blocks: gradio.Blocks) -> None: self.cwd = os.getcwd() self.favicon_path = blocks.favicon_path self.tokens = {} + self.root_path = blocks.root_path def get_blocks(self) -> gradio.Blocks: if self.blocks is None: @@ -222,15 +223,17 @@ def login(form_data: OAuth2PasswordRequestForm = Depends()): def main(request: fastapi.Request, user: str = Depends(get_current_user)): mimetypes.add_type("application/javascript", ".js") blocks = app.get_blocks() + root_path = request.scope.get("root_path", "") if app.auth is None or user is not None: config = app.get_blocks().config + config["root"] = root_path else: config = { "auth_required": True, "auth_message": blocks.auth_message, "is_space": app.get_blocks().is_space, - "root": app.get_blocks().root, + "root": root_path, } try: @@ -261,8 +264,11 @@ def api_info(serialize: bool = True): @app.get("/config/", dependencies=[Depends(login_check)]) @app.get("/config", dependencies=[Depends(login_check)]) - def get_config(): - return app.get_blocks().config + def get_config(request: fastapi.Request): + root_path = request.scope.get("root_path", "") + config = app.get_blocks().config + config["root"] = root_path + return config @app.get("/static/{path:path}") def static_resource(path: str): @@ -778,7 +784,6 @@ def read_main(): # Then run `uvicorn run:app` from the terminal and navigate to http://localhost:8000/gradio. """ blocks.dev_mode = False - blocks.root = path[:-1] if path.endswith("/") else path blocks.config = blocks.get_config_file() blocks.validate_queue_settings() gradio_app = App.create_app(blocks) diff --git a/gradio/test_data/blocks_configs.py b/gradio/test_data/blocks_configs.py index c468d0dd7ac6c..cdcad71479b22 100644 --- a/gradio/test_data/blocks_configs.py +++ b/gradio/test_data/blocks_configs.py @@ -214,7 +214,6 @@ "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600&display=swap", "https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&display=swap", ], - "root": "", "theme": "default", "layout": { "id": 5, @@ -524,7 +523,6 @@ "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600&display=swap", "https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&display=swap", ], - "root": "", "theme": "default", "layout": { "id": 5,