Repository navigation
fix(proxy): pick JSON vs HTML errors by intent, not User-Agent - #3565
mishushakov wants to merge 1 commit into
Conversation
The proxy's error templates chose the HTML page over JSON by sniffing the
User-Agent. A fetch() from page scripts carries the browser's own
User-Agent and cannot override it — UA is a forbidden header name — so an
SDK call from a browser got the HTML error page where it expects JSON,
and Accept was ignored entirely:
no UA -> 502 application/json
chrome UA -> 502 text/html
chrome UA + Accept: application/json -> 502 text/html <- ignored
Intent now decides first: JSON when Accept prefers it, or when
Sec-Fetch-Mode / X-Requested-With mark the request as script-initiated.
UA sniffing stays as the fallback, where it only catches genuine
top-level navigations — which is what the HTML pages are for.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code review is billed via overage credits. To resume reviews, an organization admin can raise the monthly limit at claude.ai/admin-settings/claude-code.
If your organization is eligible for promotional free reviews, this run could not use one — if free runs remain, retrying may succeed without raising the limit.
Once credits are available — or to retry now — reopen this pull request to trigger a review.
PR SummaryMedium Risk Overview
Reviewed by Cursor Bugbot for commit a4e309b. Bugbot is set up for automated code reviews on this repo. Configure here. |
❌ 1 Tests Failed:
View the top 1 failed test(s) by shortest run time
To view more test analytics, go to the Test Analytics Dashboard |
Extracted from #3389, which bundled this with the CORS fix. This half stands alone.
Problem
The proxy's synthesized error responses (
packages/shared/pkg/proxy/template/) chose the HTML error page over JSON by sniffing the User-Agent. Afetch()from page scripts carries the browser's own User-Agent and cannot override it — UA is a forbidden header name — so an SDK call from a browser got the HTML error page where it expects JSON.Acceptwas ignored entirely:Change
Intent decides first, in
wantsHtml:Acceptprefers JSON (application/jsonpresent,text/htmlabsent) → JSON.Sec-Fetch-Modeiscors/no-cors/same-origin, orX-Requested-Withis set → JSON. Both are set by the browser, not by the caller; a genuine top-level navigation sendsSec-Fetch-Mode: navigateinstead.This is one choke point:
TemplatedError.HandleErrorcovers all eight error templates.Tests
packages/shared/pkg/proxy/template/template_test.go— a table over the negotiation matrix (bare browser UA, navigation,Accept: application/json, cross-origin fetch, same-origin fetch, legacy XHR, no UA). Checked to have teeth by revertingwantsHtmlback toisBrowserand watching 4 cases fail.Verified with
go test -race ./packages/shared/pkg/proxy/...,make fmt,make lint. The two remaining lint failures (envd/internal/services/process/dup3_other.go,orchestrator/cmd/create-build/proxyport_test.go) are pre-existing onmainand platform-related.🤖 Generated with Claude Code