You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(proxy): extend X-Headroom-Upstream override to Gemini + /v1beta normalization
Reviewing headroomlabs-ai#1089 (the launcher-side opencode wrap) surfaced two gaps in
the initial override implementation:
1. Gemini's version segment is /v1beta (not /v1). The proxy's gemini
handlers append /v1beta/models/... themselves, so a caller passing the
versioned URL (e.g. matching headroom's _KNOWN_UPSTREAMS
'generativelanguage.googleapis.com/v1beta') would have produced a
doubled /v1beta/v1beta path. The resolver now strips a trailing /v1beta
as well as /v1.
2. The three /v1beta gemini routes did not thread the override through.
handle_gemini_generate_content and handle_gemini_count_tokens already
accepted upstream_base_url; handle_gemini_stream_generate_content did
not. All three routes now pass request_upstream_override(request), and
the stream handler gained the parameter.
Coverage is now OpenAI (/v1/chat/completions, /v1/responses), Anthropic
(/v1/messages), Gemini (/v1beta generateContent/streamGenerateContent/
countTokens), and every passthrough / catch-all route.
Copy file name to clipboardExpand all lines: CHANGELOG.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
10
10
11
11
### Features
12
12
13
-
***proxy:** per-request upstream override via the `X-Headroom-Upstream` header. A single proxy instance can now fan out to many upstreams (one per provider) instead of one proxy per upstream — the caller tags each request with its real upstream base and the proxy forwards there, overriding the startup default for that provider. The value is normalized like `*_TARGET_API_URL` (trailing slash and trailing `/v1` stripped) and the proxy appends the incoming request path. Honored on `/v1/chat/completions`, `/v1/responses`, `/v1/messages`, and every passthrough / catch-all route; stripped before the upstream call so it never leaks. Enables single-proxy multi-provider setups such as OpenCode's 75+ providers (each provider configured with `baseURL` = the proxy + an `X-Headroom-Upstream` header = its real upstream).
13
+
***proxy:** per-request upstream override via the `X-Headroom-Upstream` header. A single proxy instance can now fan out to many upstreams (one per provider) instead of one proxy per upstream — the caller tags each request with its real upstream base and the proxy forwards there, overriding the startup default for that provider. The value is normalized like `*_TARGET_API_URL` (trailing slash and a trailing `/v1`or `/v1beta` version segment stripped) and the proxy appends the incoming request path. Honored on `/v1/chat/completions`, `/v1/responses`, `/v1/messages`, `/v1beta/models/{model}:generateContent`/`:streamGenerateContent`/`:countTokens`, and every passthrough / catch-all route; stripped before the upstream call so it never leaks. Enables single-proxy multi-provider setups such as OpenCode's 75+ providers (each provider configured with `baseURL` = the proxy + an `X-Headroom-Upstream` header = its real upstream).
14
14
15
15
***proxy:** measure and surface rolling and current token throughput metrics (active/wall-clock input, compression, effective forward, and streamed generation) in `headroom perf` CLI and the dashboard ([#959](https://github.com/chopratejas/headroom/issues/959)).
16
16
***vibe:** add Mistral Vibe CLI support with `headroom wrap vibe`.
Copy file name to clipboardExpand all lines: docs/content/docs/proxy.mdx
+3-2Lines changed: 3 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -266,16 +266,17 @@ Rewriting the request body invalidates the caller's **SigV4** signature (it cove
266
266
267
267
A single Headroom proxy normally forwards to one configured upstream per provider (`OPENAI_TARGET_API_URL`, `ANTHROPIC_TARGET_API_URL`, …). The `X-Headroom-Upstream` request header overrides that upstream **per request**, so one proxy instance can fan out to many upstreams — no need to run one proxy per provider.
268
268
269
-
Set the header to the upstream base URL. It is normalized the same way as the `*_TARGET_API_URL` env vars (trailing slash and a trailing `/v1`segment are stripped), then the proxy appends the incoming request path:
269
+
Set the header to the upstream base URL. It is normalized the same way as the `*_TARGET_API_URL` env vars (trailing slash and a trailing API-version segment — `/v1`or `/v1beta` — are stripped), then the proxy appends the incoming request path:
The header is an internal `x-headroom-*` control flag: it is consumed by the proxy and stripped before the upstream call, so it never leaks to the provider. Honored on the OpenAI (`/v1/chat/completions`, `/v1/responses`), Anthropic (`/v1/messages`), and every passthrough / catch-all route.
279
+
The header is an internal `x-headroom-*` control flag: it is consumed by the proxy and stripped before the upstream call, so it never leaks to the provider. Honored on the OpenAI (`/v1/chat/completions`, `/v1/responses`), Anthropic (`/v1/messages`), Gemini (`/v1beta/models/{model}:generateContent`, `:streamGenerateContent`, `:countTokens`), and every passthrough / catch-all route.
0 commit comments