chore: Add support for reversed proxy in adk web, users can use an optional param --root_path for proxy's path

Co-authored-by: Yifan Wang <wanyif@google.com>
PiperOrigin-RevId: 826632932
This commit is contained in:
Yifan Wang
2025-10-31 14:36:58 -07:00
committed by Copybara-Service
parent 0487eea2ab
commit a0df75b6fa
3 changed files with 26 additions and 2 deletions
+9 -2
View File
@@ -436,6 +436,7 @@ class AdkWebServer:
extra_plugins: Optional[list[str]] = None,
logo_text: Optional[str] = None,
logo_image_url: Optional[str] = None,
url_prefix: Optional[str] = None,
):
self.agent_loader = agent_loader
self.session_service = session_service
@@ -452,6 +453,7 @@ class AdkWebServer:
self.runners_to_clean: set[str] = set()
self.current_app_name_ref: SharedValue[str] = SharedValue(value="")
self.runner_dict = {}
self.url_prefix = url_prefix
async def get_runner_async(self, app_name: str) -> Runner:
"""Returns the cached runner for the given app."""
@@ -559,6 +561,7 @@ class AdkWebServer:
" overwritten.",
runtime_config_path,
)
runtime_config["backendUrl"] = self.url_prefix if self.url_prefix else ""
# Set custom logo config.
if self.logo_text or self.logo_image_url:
@@ -1562,6 +1565,10 @@ class AdkWebServer:
mimetypes.add_type("application/javascript", ".js", True)
mimetypes.add_type("text/javascript", ".js", True)
redirect_dev_ui_url = (
self.url_prefix + "/dev-ui/" if self.url_prefix else "/dev-ui/"
)
@app.get("/dev-ui/config")
async def get_ui_config():
return {
@@ -1571,11 +1578,11 @@ class AdkWebServer:
@app.get("/")
async def redirect_root_to_dev_ui():
return RedirectResponse("/dev-ui/")
return RedirectResponse(redirect_dev_ui_url)
@app.get("/dev-ui")
async def redirect_dev_ui_add_slash():
return RedirectResponse("/dev-ui/")
return RedirectResponse(redirect_dev_ui_url)
app.mount(
"/dev-ui/",
+15
View File
@@ -1028,6 +1028,17 @@ def fast_api_common_options():
),
multiple=True,
)
@click.option(
"--url_prefix",
type=str,
help=(
"Optional. URL path prefix when the application is mounted behind a"
" reverse proxy or API gateway (e.g., '/api/v1', '/adk'). This"
" ensures generated URLs and redirects work correctly when the app"
" is not served at the root path. Must start with '/' if provided."
),
default=None,
)
@functools.wraps(func)
@click.pass_context
def wrapper(ctx, *args, **kwargs):
@@ -1065,6 +1076,7 @@ def cli_web(
allow_origins: Optional[list[str]] = None,
host: str = "127.0.0.1",
port: int = 8000,
url_prefix: Optional[str] = None,
trace_to_cloud: bool = False,
otel_to_cloud: bool = False,
reload: bool = True,
@@ -1128,6 +1140,7 @@ def cli_web(
a2a=a2a,
host=host,
port=port,
url_prefix=url_prefix,
reload_agents=reload_agents,
extra_plugins=extra_plugins,
logo_text=logo_text,
@@ -1164,6 +1177,7 @@ def cli_api_server(
allow_origins: Optional[list[str]] = None,
host: str = "127.0.0.1",
port: int = 8000,
url_prefix: Optional[str] = None,
trace_to_cloud: bool = False,
otel_to_cloud: bool = False,
reload: bool = True,
@@ -1203,6 +1217,7 @@ def cli_api_server(
a2a=a2a,
host=host,
port=port,
url_prefix=url_prefix,
reload_agents=reload_agents,
extra_plugins=extra_plugins,
),
+2
View File
@@ -64,6 +64,7 @@ def get_fast_api_app(
a2a: bool = False,
host: str = "127.0.0.1",
port: int = 8000,
url_prefix: Optional[str] = None,
trace_to_cloud: bool = False,
otel_to_cloud: bool = False,
reload_agents: bool = False,
@@ -144,6 +145,7 @@ def get_fast_api_app(
extra_plugins=extra_plugins,
logo_text=logo_text,
logo_image_url=logo_image_url,
url_prefix=url_prefix,
)
# Callbacks & other optional args for when constructing the FastAPI instance