Files
Nip-05-api/internal/http/middleware/cors.go
Michilis 5dcd671043 Support comma-separated CORS_HEADER for multiple origins.
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.
2026-05-06 20:38:28 +00:00

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)
})
}
}