fix(claude): send Anthropic header names with the real client's casing
CPA negotiates ALPN http/1.1 with Anthropic, so header names are not lowercased by HPACK and reach the server verbatim. The casing is therefore part of the fingerprint, and six of the eighteen names CPA emits were wrong because Go canonicalises everything passed through Header.Set: anthropic-beta, anthropic-dangerous-direct-browser-access, anthropic-version, x-app, x-client-request-id and X-Stainless-OS. Writing the map keys directly is the only way to keep the original casing. This also fixes ordering at no extra cost. Go sorts header names bytewise when it serialises a request, and the captured order of the real client is exactly that same bytewise sort. Host, User-Agent and Content-Length stay misplaced because Go writes them ahead of the sorted block; a test records that gap and will fail if it ever closes. The pass runs at the send boundary rather than inside applyClaudeHeaders: the rewritten keys are unreachable through Header.Get, and doing it earlier hid these headers from the rest of the pipeline. The boundary is a single doClaudeUpstreamRequest helper pinned by a structural test, after a mutation check showed that dropping the call from the streaming path alone was otherwise undetectable. Expected order is pinned by serialising the request and reading the header lines back, not by inspecting the header map.
S
sususu committed
a20626f1eee946c0344d3692f7c3465619f1c410
Parent: 6912a74