mirror of
https://github.com/tinode/chat.git
synced 2025-03-14 10:05:07 +00:00
Merge pull request #907 from tinode/cors
Add CORS HTTP headers to regular (non-OPTIONS) requests
This commit is contained in:
@ -80,6 +80,7 @@ func matchCORSOrigin(allowed []string, origin string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// allowMethods must be in UPPERCASE.
|
||||
func matchCORSMethod(allowMethods []string, method string) bool {
|
||||
if method == "" {
|
||||
// Request has no Method header.
|
||||
@ -88,7 +89,7 @@ func matchCORSMethod(allowMethods []string, method string) bool {
|
||||
|
||||
method = strings.ToUpper(method)
|
||||
for _, mm := range allowMethods {
|
||||
if strings.ToUpper(mm) == method {
|
||||
if mm == method {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -96,41 +97,51 @@ func matchCORSMethod(allowMethods []string, method string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// CORSHandler is the default preflight OPTIONS processor for use by media handlers.
|
||||
// CORSHandler is the default CORS processor for use by media handlers.
|
||||
func CORSHandler(req *http.Request, allowedOrigins []string, serve bool) (http.Header, int) {
|
||||
if req.Method != http.MethodOptions {
|
||||
// Not an OPTIONS request. No special handling for all other requests.
|
||||
return nil, 0
|
||||
}
|
||||
|
||||
var allowMethods []string
|
||||
if serve {
|
||||
allowMethods = []string{http.MethodGet, http.MethodHead, http.MethodOptions}
|
||||
} else {
|
||||
allowMethods = []string{http.MethodPost, http.MethodPut, http.MethodHead, http.MethodOptions}
|
||||
}
|
||||
|
||||
headers := map[string][]string{
|
||||
// Always add Vary because of possible intermediate caches.
|
||||
"Vary": {"Origin", "Access-Control-Request-Method"},
|
||||
"Access-Control-Allow-Headers": {"*"},
|
||||
"Access-Control-Max-Age": {"86400"},
|
||||
"Access-Control-Allow-Credentials": {"true"},
|
||||
"Access-Control-Allow-Methods": {strings.Join(allowMethods, ", ")},
|
||||
"Vary": {"Origin", "Access-Control-Request-Method, Access-Control-Request-Headers"},
|
||||
}
|
||||
|
||||
if !matchCORSMethod(allowMethods, req.Header.Get("Access-Control-Request-Method")) {
|
||||
// CORS policy does not allow this method.
|
||||
origin := req.Header.Get("Origin")
|
||||
|
||||
allowedOrigin := matchCORSOrigin(allowedOrigins, origin)
|
||||
requestMethod := req.Header.Get("Access-Control-Request-Method")
|
||||
if req.Method == http.MethodOptions && requestMethod != "" {
|
||||
// Preflight request.
|
||||
|
||||
if allowedOrigin == "" {
|
||||
return headers, http.StatusNoContent
|
||||
}
|
||||
|
||||
var allowMethods []string
|
||||
if serve {
|
||||
allowMethods = []string{http.MethodGet, http.MethodHead, http.MethodOptions}
|
||||
} else {
|
||||
allowMethods = []string{http.MethodPost, http.MethodPut, http.MethodHead, http.MethodOptions}
|
||||
}
|
||||
|
||||
if !matchCORSMethod(allowMethods, requestMethod) {
|
||||
// CORS policy does not allow this method.
|
||||
return headers, http.StatusNoContent
|
||||
}
|
||||
|
||||
headers["Access-Control-Allow-Headers"] = []string{"*"}
|
||||
headers["Access-Control-Allow-Credentials"] = []string{"true"}
|
||||
headers["Access-Control-Allow-Methods"] = []string{strings.Join(allowMethods, ", ")}
|
||||
headers["Access-Control-Max-Age"] = []string{"86400"}
|
||||
headers["Access-Control-Allow-Origin"] = []string{allowedOrigin}
|
||||
|
||||
return headers, http.StatusNoContent
|
||||
}
|
||||
|
||||
allowedOrigin := matchCORSOrigin(allowedOrigins, req.Header.Get("Origin"))
|
||||
if allowedOrigin == "" {
|
||||
// CORS policy does not match the origin.
|
||||
return headers, http.StatusNoContent
|
||||
// Regular request, not a preflight.
|
||||
|
||||
if allowedOrigin != "" {
|
||||
// Returning Origin from the actual request instead of '*', otherwise there could be an issue with Credentials.
|
||||
headers["Access-Control-Allow-Origin"] = []string{origin}
|
||||
}
|
||||
|
||||
headers["Access-Control-Allow-Origin"] = []string{allowedOrigin}
|
||||
|
||||
return headers, http.StatusNoContent
|
||||
return headers, 0
|
||||
}
|
||||
|
Reference in New Issue
Block a user