CORS Reflect Origin#1385
Conversation
WalkthroughThe CORS middleware in the HTTP server now supports dynamic origin reflection. When the origin configuration is set to ChangesDynamic CORS Origin Handling
Estimated code review effort🎯 2 (Simple) | ⏱️ ~15 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@pkg/server/http_server.go`:
- Around line 492-507: The CORS handling sets Access-Control-Allow-Origin
dynamically when h.options.OriginURL == "*" (computed into acao_url from
req.Header.Get("Origin")) but does not set the Vary header; add
w.Header().Add("Vary", "Origin") whenever Access-Control-Allow-Origin is
determined from the request (i.e., in the branch where h.options.OriginURL ==
"*") so both the preflight (req.Method == http.MethodOptions) and normal
response paths include Vary: Origin to prevent incorrect cached responses.
- Around line 492-506: When h.options.OriginURL == "*" only use
req.Header.Get("Origin") if it returns a non-empty string (avoid acao_url = "");
set acao_url := "" by default, then if h.options.OriginURL == "*" do origin :=
req.Header.Get("Origin"); if origin != "" { acao_url = origin } else leave
acao_url empty; for the http.MethodOptions preflight branch and the later
w.Header().Set("Access-Control-Allow-Origin", ...) call only set the
Access-Control-Allow-Origin (and related CORS headers) when acao_url != "" to
avoid emitting an empty header. Reference h.options.OriginURL,
req.Header.Get("Origin"), acao_url, http.MethodOptions and
w.Header().Set("Access-Control-Allow-Origin").
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3ff1c6ca-591c-4045-b572-2ec90947c3d7
📒 Files selected for processing (1)
pkg/server/http_server.go
| if h.options.OriginURL == "*" { | ||
| acao_url = req.Header.Get("Origin") | ||
| } else { | ||
| acao_url = h.options.OriginURL | ||
| } | ||
|
|
||
| // Set CORS headers for the preflight request | ||
| if req.Method == http.MethodOptions { | ||
| w.Header().Set("Access-Control-Allow-Origin", h.options.OriginURL) | ||
| w.Header().Set("Access-Control-Allow-Origin", acao_url) | ||
| w.Header().Set("Access-Control-Allow-Credentials", "true") | ||
| w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization") | ||
| w.WriteHeader(http.StatusNoContent) | ||
| return | ||
| } | ||
| w.Header().Set("Access-Control-Allow-Origin", h.options.OriginURL) | ||
| w.Header().Set("Access-Control-Allow-Origin", acao_url) |
There was a problem hiding this comment.
Avoid emitting empty Access-Control-Allow-Origin when request has no Origin.
In wildcard mode, non-CORS requests can produce Access-Control-Allow-Origin: "". Prefer setting CORS headers only when Origin is present (or explicitly fallback behavior), so headers stay valid and predictable.
Suggested patch
- var acao_url string
+ var acao_url string
+ shouldSetCORS := true
if h.options.OriginURL == "*" {
acao_url = req.Header.Get("Origin")
+ if acao_url == "" {
+ shouldSetCORS = false
+ }
} else {
acao_url = h.options.OriginURL
}
@@
- w.Header().Set("Access-Control-Allow-Origin", acao_url)
- w.Header().Set("Access-Control-Allow-Credentials", "true")
- w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
+ if shouldSetCORS {
+ w.Header().Set("Access-Control-Allow-Origin", acao_url)
+ w.Header().Set("Access-Control-Allow-Credentials", "true")
+ w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
+ }
w.WriteHeader(http.StatusNoContent)
return
}
- w.Header().Set("Access-Control-Allow-Origin", acao_url)
- w.Header().Set("Access-Control-Allow-Credentials", "true")
- w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
+ if shouldSetCORS {
+ w.Header().Set("Access-Control-Allow-Origin", acao_url)
+ w.Header().Set("Access-Control-Allow-Credentials", "true")
+ w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
+ }
next.ServeHTTP(w, req)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@pkg/server/http_server.go` around lines 492 - 506, When h.options.OriginURL
== "*" only use req.Header.Get("Origin") if it returns a non-empty string (avoid
acao_url = ""); set acao_url := "" by default, then if h.options.OriginURL ==
"*" do origin := req.Header.Get("Origin"); if origin != "" { acao_url = origin }
else leave acao_url empty; for the http.MethodOptions preflight branch and the
later w.Header().Set("Access-Control-Allow-Origin", ...) call only set the
Access-Control-Allow-Origin (and related CORS headers) when acao_url != "" to
avoid emitting an empty header. Reference h.options.OriginURL,
req.Header.Get("Origin"), acao_url, http.MethodOptions and
w.Header().Set("Access-Control-Allow-Origin").
| if h.options.OriginURL == "*" { | ||
| acao_url = req.Header.Get("Origin") | ||
| } else { | ||
| acao_url = h.options.OriginURL | ||
| } | ||
|
|
||
| // Set CORS headers for the preflight request | ||
| if req.Method == http.MethodOptions { | ||
| w.Header().Set("Access-Control-Allow-Origin", h.options.OriginURL) | ||
| w.Header().Set("Access-Control-Allow-Origin", acao_url) | ||
| w.Header().Set("Access-Control-Allow-Credentials", "true") | ||
| w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization") | ||
| w.WriteHeader(http.StatusNoContent) | ||
| return | ||
| } | ||
| w.Header().Set("Access-Control-Allow-Origin", h.options.OriginURL) | ||
| w.Header().Set("Access-Control-Allow-Origin", acao_url) | ||
| w.Header().Set("Access-Control-Allow-Credentials", "true") |
There was a problem hiding this comment.
Add Vary: Origin when Access-Control-Allow-Origin is dynamic.
When OriginURL == "*", Access-Control-Allow-Origin varies per request origin, but the response currently does not advertise that variance. Shared caches/CDNs can serve a response with the wrong CORS origin to another client.
Suggested patch
if h.options.OriginURL == "*" {
acao_url = req.Header.Get("Origin")
+ w.Header().Add("Vary", "Origin")
} else {
acao_url = h.options.OriginURL
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if h.options.OriginURL == "*" { | |
| acao_url = req.Header.Get("Origin") | |
| } else { | |
| acao_url = h.options.OriginURL | |
| } | |
| // Set CORS headers for the preflight request | |
| if req.Method == http.MethodOptions { | |
| w.Header().Set("Access-Control-Allow-Origin", h.options.OriginURL) | |
| w.Header().Set("Access-Control-Allow-Origin", acao_url) | |
| w.Header().Set("Access-Control-Allow-Credentials", "true") | |
| w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization") | |
| w.WriteHeader(http.StatusNoContent) | |
| return | |
| } | |
| w.Header().Set("Access-Control-Allow-Origin", h.options.OriginURL) | |
| w.Header().Set("Access-Control-Allow-Origin", acao_url) | |
| w.Header().Set("Access-Control-Allow-Credentials", "true") | |
| if h.options.OriginURL == "*" { | |
| acao_url = req.Header.Get("Origin") | |
| w.Header().Add("Vary", "Origin") | |
| } else { | |
| acao_url = h.options.OriginURL | |
| } | |
| // Set CORS headers for the preflight request | |
| if req.Method == http.MethodOptions { | |
| w.Header().Set("Access-Control-Allow-Origin", acao_url) | |
| w.Header().Set("Access-Control-Allow-Credentials", "true") | |
| w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization") | |
| w.WriteHeader(http.StatusNoContent) | |
| return | |
| } | |
| w.Header().Set("Access-Control-Allow-Origin", acao_url) | |
| w.Header().Set("Access-Control-Allow-Credentials", "true") |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@pkg/server/http_server.go` around lines 492 - 507, The CORS handling sets
Access-Control-Allow-Origin dynamically when h.options.OriginURL == "*"
(computed into acao_url from req.Header.Get("Origin")) but does not set the Vary
header; add w.Header().Add("Vary", "Origin") whenever
Access-Control-Allow-Origin is determined from the request (i.e., in the branch
where h.options.OriginURL == "*") so both the preflight (req.Method ==
http.MethodOptions) and normal response paths include Vary: Origin to prevent
incorrect cached responses.
Updates the CORS middleware behavior when
OriginURLis configured as*, which is the default value.Previously, the server returned:
This combination is invalid for credentialed CORS requests. Browsers reject CORS responses that use Access-Control-Allow-Origin: * together with Access-Control-Allow-Credentials: true.
With this change, when OriginURL is set to *, the middleware reflects the incoming request's Origin header instead of returning * directly.
If OriginURL is configured with a specific value, the existing behavior is preserved and that configured value is returned as Access-Control-Allow-Origin.
This keeps the default CORS behavior permissive while making credentialed CORS requests valid according to browser CORS enforcement rules.
Without this change, cross-origin requests using credentials may fail even though the server explicitly sets Access-Control-Allow-Credentials: true.
Summary by CodeRabbit