Skip to content

fix(url-util): infer backendUrl from location when behind a path-prefixing proxy - #516

Open
luissilva-mollie wants to merge 1 commit into
google:mainfrom
luissilva-mollie:fix/backend-url-behind-path-prefix
Open

fix(url-util): infer backendUrl from location when behind a path-prefixing proxy#516
luissilva-mollie wants to merge 1 commit into
google:mainfrom
luissilva-mollie:fix/backend-url-behind-path-prefix

Conversation

@luissilva-mollie

Copy link
Copy Markdown

Fixes #515.

Problem

URLUtil.getApiServerBaseUrl() defaults to '' (root-relative) when runtimeConfig.backendUrl isn't configured. That's fine when adk-web is served at the server root, but breaks any deployment behind a path-prefixing reverse proxy that strips its prefix before forwarding to the backend: the UI loads correctly at e.g. /agents/my-agent/dev-ui/, but its API calls go out root-relative (GET /list-apps) and the proxy has no route for that.

runtime-config.json can be customized via set-backend.js, but that only runs at build time against the source tree. Backends that embed an already-built adk-web bundle as a packaged dependency (e.g. adk-java's AdkWebServer, serving classpath:/browser/** out of the google-adk-dev jar) have no build step to run it against, and the file is sealed inside a jar at runtime — so there was no way to get a correct backendUrl in that scenario without patching the frontend.

getBaseUrlWithoutPath() (used as the OAuth redirectUri) had the same class of bug: it hardcodes origin + '/dev-ui/', discarding any prefix.

Fix

When backendUrl isn't explicitly configured, derive a same-origin default from window.location that preserves whatever path prefix the app is itself mounted under (by locating /dev-ui in location.pathname and taking everything before it as the mount root), instead of always assuming the API lives at the server root. Applied the same fix to getBaseUrlWithoutPath().

An explicit runtimeConfig.backendUrl (e.g. set via set-backend.js for local dev) still takes precedence, so local dev workflows are unaffected.

Refactored the three URLUtil methods to accept an optional Location-like parameter (defaulting to window.location) purely for testability — window.location isn't reconfigurable in a real browser, so this was needed to unit test the new branching without reaching for a more invasive mocking setup.

Testing

  • Added src/utils/url-util.spec.ts covering both the unprefixed and reverse-proxy-prefixed cases for all three methods, plus the "explicit config wins" case.
  • ng test (full suite): 650 passed, no regressions.
  • ng build: succeeds.

…ixing proxy

Backends that embed the prebuilt adk-web bundle (e.g. adk-java's
AdkWebServer) serve runtime-config.json straight out of their own
packaged artifact and have no build step to run set-backend.js against,
so backendUrl is always "". URLUtil.getApiServerBaseUrl() then falls back
to root-relative API calls (GET /list-apps), which breaks behind any
reverse proxy that strips a path prefix before forwarding to the backend
(e.g. WAP-style routing: /agents/my-agent/* -> container, prefix
stripped) — the browser calls the unprefixed path and the proxy 404s.

Derive a same-origin default from window.location instead of defaulting
to root-relative, preserving whatever prefix this app was itself loaded
under. An explicit runtimeConfig.backendUrl still takes precedence, so
local dev via set-backend.js is unaffected. Also fixes
getBaseUrlWithoutPath(), which hardcoded "/dev-ui/" off the origin and
dropped any prefix the same way.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

backendUrl defaults to root-relative, breaking deployments behind a path-prefixing reverse proxy

1 participant