Parse CORS_HEADER as a list: * for all origins, or reflect matching request Origin when multiple specific origins are configured. Add Vary: Origin for the allowlist case. Update .env.example and CORS tests.
55 lines
1.4 KiB
Go
55 lines
1.4 KiB
Go
package middleware
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/noderunners/nip05api/internal/config"
|
|
)
|
|
|
|
// CORS sets Access-Control-Allow-Origin based on the CORS_HEADER env var.
|
|
//
|
|
// Supports "*" (allow all), a single origin, or a comma-separated list.
|
|
// When multiple origins are configured the middleware reflects the request
|
|
// Origin back if it matches one of the allowed values (the HTTP spec forbids
|
|
// sending more than one origin in the header).
|
|
func CORS(cfg *config.Config) func(http.Handler) http.Handler {
|
|
allowAll := len(cfg.CORSOrigins) == 1 && cfg.CORSOrigins[0] == "*"
|
|
|
|
allowed := make(map[string]bool, len(cfg.CORSOrigins))
|
|
for _, o := range cfg.CORSOrigins {
|
|
allowed[o] = true
|
|
}
|
|
|
|
return func(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
var origin string
|
|
if allowAll {
|
|
origin = "*"
|
|
} else {
|
|
reqOrigin := r.Header.Get("Origin")
|
|
if allowed[reqOrigin] {
|
|
origin = reqOrigin
|
|
}
|
|
}
|
|
|
|
if origin != "" {
|
|
h := w.Header()
|
|
h.Set("Access-Control-Allow-Origin", origin)
|
|
h.Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
|
|
h.Set("Access-Control-Allow-Headers", "Content-Type, X-API-Key, Authorization")
|
|
h.Set("Access-Control-Max-Age", "86400")
|
|
if !allowAll {
|
|
h.Set("Vary", "Origin")
|
|
}
|
|
}
|
|
|
|
if r.Method == http.MethodOptions {
|
|
w.WriteHeader(http.StatusNoContent)
|
|
return
|
|
}
|
|
|
|
next.ServeHTTP(w, r)
|
|
})
|
|
}
|
|
}
|