package mw import "net/http" const ( allowedMethods = "GET, HEAD, PUT, PATCH, POST, DELETE, OPTIONS" allowedHeaders = "Content-Type, Authorization, X-Request-ID" ) // CORS sets cross-origin resource sharing headers for the provided origins. // Returns 204 No Content for OPTIONS preflight requests. // Pass the outermost origins first; an empty slice is a no-op. func CORS(origins []string) func(http.Handler) http.Handler { originSet := make(map[string]struct{}, len(origins)) for _, o := range origins { originSet[o] = struct{}{} } return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { origin := r.Header.Get("Origin") if origin != "" { if _, allowed := originSet[origin]; allowed { w.Header().Set("Access-Control-Allow-Origin", origin) w.Header().Set("Access-Control-Allow-Methods", allowedMethods) w.Header().Set("Access-Control-Allow-Headers", allowedHeaders) w.Header().Set("Access-Control-Allow-Credentials", "true") w.Header().Set("Vary", "Origin") } } if r.Method == http.MethodOptions { w.WriteHeader(http.StatusNoContent) return } next.ServeHTTP(w, r) }) } } // CORSAllowAll is a convenience wrapper that allows any origin. // Use only in development — never in production. func CORSAllowAll() func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { origin := r.Header.Get("Origin") if origin == "" { origin = "*" } w.Header().Set("Access-Control-Allow-Origin", origin) w.Header().Set("Access-Control-Allow-Methods", allowedMethods) w.Header().Set("Access-Control-Allow-Headers", allowedHeaders) w.Header().Set("Vary", "Origin") if r.Method == http.MethodOptions { w.WriteHeader(http.StatusNoContent) return } next.ServeHTTP(w, r) }) } }