fix(14-05): surf answers OPTIONS on CORS paths with Laravel's HandleCors headers
- every OPTIONS on a CORS path: 204 with Cache-Control no-cache, private - a preflight echoes the requested method (upper-cased) and headers when * allows any, with Vary and PHP's default Content-Type, as recorded from PHP - README and the routing docs describe the answer
This commit is contained in:
@@ -94,13 +94,43 @@ func pathScopedCORS(cfg CORSConfig, next http.Handler) http.Handler {
|
||||
}
|
||||
}
|
||||
if r.Method == http.MethodOptions {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
writeOptions(w, r, allowed, allowAnyMethod, allowAnyHeader)
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
// writeOptions answers an OPTIONS request on a CORS path with 204 and the
|
||||
// headers Laravel's HandleCors (fruitcake/php-cors) sends, so recorded PHP
|
||||
// preflights replay unchanged. Every answer carries Symfony's default
|
||||
// Cache-Control "no-cache, private". A preflight (an Origin and an
|
||||
// Access-Control-Request-Method) also carries the Content-Type PHP's SAPI
|
||||
// adds to a response that sets none ("text/html; charset=UTF-8") and Vary
|
||||
// on the two request headers; when any method or header is allowed, the
|
||||
// Allow-Methods and Allow-Headers values echo the requested method
|
||||
// (upper-cased) and headers, as php-cors does, instead of "*".
|
||||
func writeOptions(w http.ResponseWriter, r *http.Request, allowed, allowAnyMethod, allowAnyHeader bool) {
|
||||
h := w.Header()
|
||||
h.Set("Cache-Control", "no-cache, private")
|
||||
method := r.Header.Get("Access-Control-Request-Method")
|
||||
if r.Header.Get("Origin") != "" && method != "" {
|
||||
h.Set("Content-Type", "text/html; charset=UTF-8")
|
||||
h.Add("Vary", "Access-Control-Request-Method, Access-Control-Request-Headers")
|
||||
if allowed && allowAnyMethod {
|
||||
h.Set("Access-Control-Allow-Methods", strings.ToUpper(method))
|
||||
}
|
||||
if allowed && allowAnyHeader {
|
||||
if requested := r.Header.Get("Access-Control-Request-Headers"); requested != "" {
|
||||
h.Set("Access-Control-Allow-Headers", requested)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
h.Add("Vary", "Access-Control-Request-Method")
|
||||
}
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func corsAllowOrigin(allowAny bool, origins map[string]struct{}, pats []*regexp.Regexp, origin string) (bool, string) {
|
||||
if allowAny {
|
||||
return true, "*"
|
||||
|
||||
Reference in New Issue
Block a user