Build signed object URLs as path-only (/api/objects/...) instead of prefixing APP_BASE_URL, so media loads from whatever host or reverse proxy served the app. Remove the now-unused base URL from the signer and drop the APP_BASE_URL / Server.BaseURL config.
2.9 KiB
Design
Context
See proposal.md - Why. Relevant current state:
storage.Signer.URLbuildsbaseURL + "/api/objects/<key>?e&s"(signer.go), withbaseURLfromcfg.Server.BaseURL(APP_BASE_URL, defaulthttp://localhost:8080).- That absolute URL is the only use of
Server.BaseURL; SSE and API traffic are already root-relative (/api/...). photos.Service.attachURLsruns outside an HTTP request, so it cannot see the request host to derive a base.
Goals / Non-Goals
Goals:
- Photo/preview URLs work on any host or reverse proxy with no per-deployment base URL.
- Preserve signing, expiry, quantization and caching behavior exactly.
Non-Goals:
- Serving the app under a URL subpath.
- Absolute URL generation for non-browser consumers (no such consumer today).
- Changing the object route, storage backends, or delivery semantics.
Decisions
Emit origin-relative (path-only) object URLs
Signer.URL(key) returns "/api/objects/<escaped-key>?e=<exp>&s=<sig>". A leading slash
makes it origin-relative: the browser resolves it against the page's scheme/host/port,
which is exactly the backend that served the page.
- Alternative considered: keep absolute URLs and require operators to set
APP_BASE_URL. Rejected - this is the current footgun; a wrong or default value silently breaks all images. - Alternative considered: derive the base from the request (
Host,X-Forwarded-Proto). Rejected - URLs are minted inattachURLs/SSE paths that have no request; threading a base through every service is invasive for no benefit once URLs are relative. - Alternative considered: document-relative URLs without a leading slash. Rejected - the app and its API calls already use root-relative paths, so root-relative is consistent.
Remove the base URL from the signer and config
Drop the baseURL field and parameter from Signer/NewSigner, stop reading
cfg.Server.BaseURL in storage.Open, and remove Server.BaseURL from config,
.env.example and the README. Leaving a now-unused variable would invite the same
misconfiguration.
Verification unchanged
VerifyRequest checks the key and query (e, s) only; it never used the host, so
signing and validation are untouched.
Risks / Trade-offs
- [Subpath deployment (
https://host/galo/) would break with root-relative URLs] -> The app already assumes root (/api/...); subpath support would be a separate change adding a base-path prefix. Documented as out of scope. - [Non-browser clients need a base to resolve object URLs] -> None consume them today; if one appears, it resolves against the instance base like any HTTP client.
- [Tests that assumed an absolute URL] -> They parse the URL and use
Path/RawQuery; updateNewSignercall sites to drop the base argument.
Migration Plan
Remove APP_BASE_URL from the server environment and deploy the backend. No data or
schema change. Rollback is reverting the deploy.
Open Questions
None blocking.