fix(web): proxy binary downloads through the BFF (BUNYIP-64) #82
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/bunyip-64-download-asset-bff-proxy"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
Clicking Download on the Downloads page saved an HTML file instead of the binary (e.g. the vervain-agent binary came down as HTML). bunyip-api builds the asset link as the root-relative API path
/v1/applications/{slug}/downloads/{asset}, but that anchor is rendered in a bunyip-web page, so the browser resolved it against the bunyip-web origin, not bunyip-api. bunyip-web had no matching route, so the request hit thenot_foundHTML fallback, and because the anchor carried adownloadattribute the browser saved that 404 page under the asset's filename.Fix
bunyip-web is the browser-facing BFF: the session cookie is scoped to its origin and the browser must never call bunyip-api directly. This adds a streaming proxy route
GET /downloads/{slug}/{asset}that re-auths the session, forwards the cookie to the API's membership/entitlement-gated download endpoint, and relays the bytes with the upstreamContent-Type/Content-Disposition.Api::get_streamreturns the rawreqwest::Responseso a large asset streams through rather than buffering in memory.The asset anchor now targets this proxy on the web origin and drops the
downloadattribute: success is driven by the proxy'sContent-Disposition, and any non-2xx (expired session, lost entitlement, upstream outage) navigates the browser (sign-in on 401, the downloads page otherwise) rather than being saved as the file.OCI check (per the issue)
OCI distribution is not affected. Container images are pulled by the docker client via the
docker login/docker pullcommand blocks shown on the page, not a browserdownloadanchor, so they never resolve against the web origin's HTML fallback. No change needed there.Test
just check-containergreen: fmt + clippy (-D warnings) + workspace lib tests all pass.#BUNYIP-64
The download link pointed at the API path `/v1/applications/{slug}/downloads/{asset}`, a root-relative URL that the browser resolved against the bunyip-web origin instead of bunyip-api. bunyip-web had no such route, so the request fell through to the `not_found` HTML fallback, and because the anchor carried a `download` attribute the browser saved that HTML 404 page under the asset's filename. That is the "downloads download an HTML file" symptom (e.g. the vervain-agent binary came down as HTML). bunyip-web is the browser-facing BFF: the session cookie is scoped to its origin and the browser must never call bunyip-api directly. Add a streaming proxy route `GET /downloads/{slug}/{asset}` that re-auths the session, forwards the cookie to the API's gated download endpoint, and relays the bytes with the upstream Content-Type / Content-Disposition. `Api::get_stream` returns the raw `reqwest::Response` so a large asset streams through rather than buffering in memory. The asset anchor now targets this proxy on the web origin and no longer sets a `download` attribute: success is driven by the proxy's Content-Disposition, and a non-2xx response (expired session, lost entitlement, upstream outage) navigates the browser (sign-in on 401, the downloads page otherwise) instead of being saved as the file. OCI distribution is unaffected: container images are pulled by the docker client via the `docker login` / `docker pull` command blocks, not a browser `download` anchor, so they never hit the web origin's HTML fallback. #BUNYIP-64 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>