feat: aggkit-proxy: add CORS support for REST and WebSocket endpoints - #1807
Merged
Conversation
…ake too WebSocket upgrades aren't gated by Access-Control-* response headers the way REST responses are (browsers never CORS-preflight the Upgrade request), so REST.CORS.AllowedOrigins previously had no effect on the tracker's WebSocket endpoint: it accepted any origin unconditionally, regardless of how REST CORS was configured. - common.CORSConfig gains OriginAllowed(origin), for callers that must reject cross-origin access themselves instead of relying on rs/cors response headers. Disabled CORS (the default) allows any origin, preserving current behavior; enabled, it mirrors rs/cors's own matching (case-insensitive, "*", single embedded wildcard per entry). - bridgetracker.Config gains a programmatic CORS field, wired from the proxy's REST.CORS by the binary (proxy/cmd/run.go) and threaded through to a per-instance websocket.Upgrader whose CheckOrigin calls OriginAllowed. - Also fixes an unrelated bug in the CORS commit this branches from: rs/cors always answers Access-Control-Allow-Origin: * when AllowedOrigins contains "*", even with AllowCredentials set, which browsers reject outright. corsHandler now routes that combination through AllowOriginFunc so the origin is actually reflected, matching the documented intent. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 13c8c89f2d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ow all
rs/cors treats an empty AllowedOrigins as its own zero-value default of
"allow every origin" (its docs say as much), which is the opposite of what
CORSConfig.AllowedOrigins documents ("Ignored ... when empty") and of
OriginAllowed's fail-closed behavior used by the WebSocket handshake.
Concretely: enabling CORS without filling in AllowedOrigins silently opened
the REST server to every origin while the WebSocket endpoint denied every
origin under the same config — an inconsistency an operator would only
discover by testing both surfaces.
corsHandler now forces deny-all via AllowOriginFunc when AllowedOrigins is
empty, matching the documented intent and OriginAllowed.
Also updates the proxy's default [REST.CORS] section: AllowedMethods and
AllowedHeaders now cover the common REST verbs and any header (still
Enabled = false, so this changes nothing until an operator opts in), and
AllowedOrigins gets a comment pointing at ["*"] for anyone who wants to
allow every origin instead of denying by default.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
taylanpince
approved these changes
Aug 20, 2026
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.
🔄 Changes Summary
REST.CORSconfig on the sharedRESTConfig/HTTPServer(common/config.go,common/httpserver.go):Enabled,AllowedOrigins,AllowedMethods,AllowedHeaders,AllowCredentials,MaxAge. Wraps the gin engine withrs/corswhen enabled. Disabled by default — no behavior change for existing deployments.[REST.CORS]section added to the proxy's default config (proxy/config/default.go), disabled, withAllowedMethods/AllowedHeaderscovering the common REST verbs and any header, ready to flip on.Upgraderequest, soAccess-Control-*headers can't restrict it — instead the handshake itself is rejected (403) for a disallowed origin, via a newCORSConfig.OriginAllowedcheck wired fromREST.CORSdown intobridgetracker.Config→wsHandler'swebsocket.Upgrader.CheckOrigin. With CORS disabled (default), the WS endpoint stays fully public, same as before.corsHandlermapsAllowedOriginsontors/cors:rs/corsalways answersAccess-Control-Allow-Origin: *whenAllowedOriginscontains"*", even withAllowCredentialsset — browsers reject that combination outright. Now routed throughAllowOriginFuncso the origin is actually reflected, matching the documented intent.rs/corstreats an emptyAllowedOriginsas its own default of "allow every origin" — the opposite of whatCORSConfig.AllowedOriginsdocuments and ofOriginAllowed's fail-closed behavior for the WebSocket handshake. Enabling CORS without filling inAllowedOriginsused to silently open the REST server to every origin while denying the WS endpoint under the same config. Now forced to deny-all viaAllowOriginFunc, consistent with the docs and with WS.docs/common_config.mdanddocs/bridgetracker/API.mdupdated accordingly.[REST.CORS]section on everyRESTConfig-backed service (proxy, aggsender-rpc, bridgeservice, autoclaim-api, …), not just the proxy. Fully backward-compatible:Enableddefaults tofalse.📋 Config Updates
✅ Testing
common/httpserver_test.go(CORS disabled/enabled, preflight,AllowCredentials+wildcard reflection, empty-AllowedOriginsdeny-all,corsHandlermapping),common/config_test.go(CORSConfig.OriginAllowedtable),bridgetracker/websocket_test.go(TestWSCORSOriginCheck: handshake allowed/rejected per origin policy).make test-unit,make lintboth pass.🐞 Issues
📝 Notes
RESTConfig/HTTPServerlevel rather than proxy-specific, so any service built on it gets the capability for free.docs/bridgetracker/API.md.🤖 Generated with Claude Code