fix(proxy): honor x-headroom-base-url on /v1/messages route#1763
Open
adryanev wants to merge 2 commits into
Open
fix(proxy): honor x-headroom-base-url on /v1/messages route#1763adryanev wants to merge 2 commits into
adryanev wants to merge 2 commits into
Conversation
The Anthropic Messages route ignored the x-headroom-base-url per-request upstream override and unconditionally forwarded to api.anthropic.com. handle_anthropic_messages already supports upstream_base_url; the route just never passed it. Clients speaking the Anthropic wire format against a non-Anthropic gateway (e.g. OpenCode Zen) were rejected upstream. Read and trim the header at the route and pass it through, matching the OpenAI-compatible and generic passthrough routes. Fixes headroomlabs-ai#1760
Contributor
PR governanceThis PR follows the template and is marked ready for human review. |
Add a Per-Request Overrides subsection describing the x-headroom-base-url proxy header and a CHANGELOG entry for the /v1/messages fix (headroomlabs-ai#1760).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
The Anthropic Messages route (
POST /v1/messages) ignored thex-headroom-base-urlper-request upstream override and unconditionally forwarded toapi.anthropic.com.handle_anthropic_messagesalready acceptsupstream_base_url(it builds the upstream URL viabuild_copilot_upstream_url), but the route never passed it. Clients that speak the Anthropic Messages wire format while authenticating against a non-Anthropic gateway (e.g. OpenCode Zen's "Go" tier) were forwarded to the real Anthropic API, which rejected the gateway key with401 invalid x-api-key.The route now reads and trims
x-headroom-base-urland passes it through asupstream_base_url, mirroring the OpenAI-compatible routes and the generic passthrough route (proxy_routes.py:996).Closes #1760
Type of Change
Changes Made
headroom/providers/proxy_routes.py: the/v1/messagesroute readsx-headroom-base-url; when present it strips whitespace and a trailing slash and passes the value asupstream_base_urltohandle_anthropic_messages. Absent or whitespace-only headers keep the previous default (api.anthropic.com).tests/test_proxy/test_anthropic_upstream_header.py: new test module pinning the route contract (header present, absent, empty, whitespace-only, trimming + trailing-slash stripping).docs/content/docs/configuration.mdx: new "Proxy upstream override (x-headroom-base-url)" subsection under Per-Request Overrides documenting the header across the OpenAI, Anthropic Messages, and passthrough routes.CHANGELOG.md:Unreleased > Fixedentry for the/v1/messagesoverride.Testing
pytest)ruff check .)mypy headroom)Test Output
Real Behavior Proof
Ran the actual
headroom proxyagainst a local mock upstream (a tiny HTTP server on127.0.0.1:9911that logs the path it receives) to reproduce the issue's before/after.Environment: local, macOS, Python 3.12; ran
headroom proxy --port 8799against a local mock upstream (a tiny HTTP server on127.0.0.1:9911that logs the path it receives).Exact command / steps: started the proxy and the mock upstream, then sent one
POST /v1/messageswith the override header and one without it (negative control), using these twocurlcommands.Observed result: with the header, the mock upstream logged
HIT path=/v1/messages x-api-key=zen-test-keyand the proxy returnedHTTP 200, confirming the request was routed to<x-headroom-base-url>/v1/messagescarrying the gateway key. Without the header, the request went to the realapi.anthropic.com(returnedHTTP 401with a genuinerequest_idand{"type":"authentication_error","message":"invalid x-api-key"}) and the mock received no additional hit — matching the pre-fix behavior in the issue. Also verified by TDD: the two override unit cases failed before the route change (assert None == 'https://opencode.ai/zen/go') and passed after it; all 4 new cases and 49 related proxy tests are green.Not tested: a request against the real OpenCode Zen gateway (no credentials); the gateway path is verified with a local mock upstream instead.
Review Readiness
Checklist
Additional Notes
/v1/messages. The related/v1/messages/count_tokensroute uses a fixed passthrough target and is out of scope for this issue.