mirror of
https://github.com/coder/coder.git
synced 2025-07-06 15:41:45 +00:00
The problem is that the headers get doubled up (not overwritten) and browsers do not like multiple values for the allowed origin even though it appears the spec allows for it. We could prefer the application's headers instead of ours but since we control OPTIONS I think preferring ours will by the more consistent experience and also aligns with the original RFC.
76 lines
2.1 KiB
Go
76 lines
2.1 KiB
Go
package httpmw
|
|
|
|
import (
|
|
"net/http"
|
|
"net/url"
|
|
"regexp"
|
|
|
|
"github.com/go-chi/cors"
|
|
|
|
"github.com/coder/coder/coderd/httpapi"
|
|
)
|
|
|
|
const (
|
|
// Server headers.
|
|
AccessControlAllowOriginHeader = "Access-Control-Allow-Origin"
|
|
AccessControlAllowCredentialsHeader = "Access-Control-Allow-Credentials"
|
|
AccessControlAllowMethodsHeader = "Access-Control-Allow-Methods"
|
|
AccessControlAllowHeadersHeader = "Access-Control-Allow-Headers"
|
|
VaryHeader = "Vary"
|
|
|
|
// Client headers.
|
|
OriginHeader = "Origin"
|
|
AccessControlRequestMethodsHeader = "Access-Control-Request-Methods"
|
|
AccessControlRequestHeadersHeader = "Access-Control-Request-Headers"
|
|
)
|
|
|
|
//nolint:revive
|
|
func Cors(allowAll bool, origins ...string) func(next http.Handler) http.Handler {
|
|
if len(origins) == 0 {
|
|
// The default behavior is '*', so putting the empty string defaults to
|
|
// the secure behavior of blocking CORs requests.
|
|
origins = []string{""}
|
|
}
|
|
if allowAll {
|
|
origins = []string{"*"}
|
|
}
|
|
return cors.Handler(cors.Options{
|
|
AllowedOrigins: origins,
|
|
// We only need GET for latency requests
|
|
AllowedMethods: []string{http.MethodOptions, http.MethodGet},
|
|
AllowedHeaders: []string{"Accept", "Content-Type", "X-LATENCY-CHECK", "X-CSRF-TOKEN"},
|
|
// Do not send any cookies
|
|
AllowCredentials: false,
|
|
})
|
|
}
|
|
|
|
func WorkspaceAppCors(regex *regexp.Regexp, app httpapi.ApplicationURL) func(next http.Handler) http.Handler {
|
|
return cors.Handler(cors.Options{
|
|
AllowOriginFunc: func(r *http.Request, rawOrigin string) bool {
|
|
origin, err := url.Parse(rawOrigin)
|
|
if rawOrigin == "" || origin.Host == "" || err != nil {
|
|
return false
|
|
}
|
|
subdomain, ok := httpapi.ExecuteHostnamePattern(regex, origin.Host)
|
|
if !ok {
|
|
return false
|
|
}
|
|
originApp, err := httpapi.ParseSubdomainAppURL(subdomain)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
return ok && originApp.Username == app.Username
|
|
},
|
|
AllowedMethods: []string{
|
|
http.MethodHead,
|
|
http.MethodGet,
|
|
http.MethodPost,
|
|
http.MethodPut,
|
|
http.MethodPatch,
|
|
http.MethodDelete,
|
|
},
|
|
AllowedHeaders: []string{"*"},
|
|
AllowCredentials: true,
|
|
})
|
|
}
|