Skip to content

Commit 91f788e

Browse files
committed
improved cors handling
* fixed error due to misunderstanding about behaviour when `Origin` header is not set despite cors being _enabled_ * preflight requests now only return the ACA-Header if the corresponding ACR-Header was present and matches where found / any allowed values where set on server-side
1 parent b25e13a commit 91f788e

1 file changed

Lines changed: 48 additions & 6 deletions

File tree

internals/proxy/middlewares/cors.go

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package middlewares
33
import (
44
"net/http"
55
"net/url"
6+
"slices"
67
"strings"
78

89
"github.com/codeshelldev/secured-signal-api/internals/config"
@@ -31,6 +32,12 @@ func corsHandler(next http.Handler) http.Handler {
3132
}
3233

3334
origin := req.Header.Get("Origin")
35+
36+
if origin == "" {
37+
next.ServeHTTP(w, req)
38+
return
39+
}
40+
3441
originURL, err := url.Parse(origin)
3542

3643
var matchingOrigin *structure.Origin
@@ -50,14 +57,49 @@ func corsHandler(next http.Handler) http.Handler {
5057

5158
w.Header().Set("Access-Control-Allow-Origin", origin)
5259

53-
w.Header().Set("Access-Control-Allow-Credentials", "true")
54-
60+
// CORS preflight request
5561
if req.Method == "OPTIONS" {
56-
methods := matchingOrigin.Methods.ValueOrFallback(defaultMethods)
57-
headers := matchingOrigin.Headers.ValueOrFallback(defaultHeaders)
62+
requestedMethod := req.Header.Get("Access-Control-Request-Method")
63+
64+
if requestedMethod != "" {
65+
allowedMethods := matchingOrigin.Methods.ValueOrFallback(defaultMethods)
66+
67+
if len(allowedMethods) != 0 {
68+
// only set if any (matching) methods
69+
w.Header().Set("Access-Control-Allow-Methods", strings.Join(allowedMethods, ","))
70+
}
71+
}
5872

59-
w.Header().Set("Access-Control-Allow-Methods", strings.Join(methods, ","))
60-
w.Header().Set("Access-Control-Allow-Headers", strings.Join(headers, ","))
73+
requestedHeaders := req.Header.Get("Access-Control-Request-Headers")
74+
75+
if requestedHeaders != "" {
76+
allowedHeaders := matchingOrigin.Headers.ValueOrFallback(defaultHeaders)
77+
78+
matchingHeaders := []string{}
79+
80+
// echo back allowed and requested headers
81+
for header := range strings.SplitSeq(requestedHeaders, ",") {
82+
header = strings.TrimSpace(header)
83+
84+
var match string
85+
86+
if slices.ContainsFunc(allowedHeaders, func(allowed string) bool {
87+
if strings.EqualFold(header, allowed) {
88+
match = allowed
89+
return true
90+
}
91+
92+
return false
93+
}) {
94+
matchingHeaders = append(matchingHeaders, match)
95+
}
96+
}
97+
98+
if len(matchingHeaders) != 0 {
99+
// only set if any (matching) headers
100+
w.Header().Set("Access-Control-Allow-Headers", strings.Join(matchingHeaders, ","))
101+
}
102+
}
61103

62104
w.WriteHeader(http.StatusNoContent)
63105

0 commit comments

Comments
 (0)