99 lines
3.5 KiB
Go
99 lines
3.5 KiB
Go
// Package middleware provides HTTP middleware for services.
|
|
package middleware
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/go-chi/cors"
|
|
)
|
|
|
|
// CORSConfig configures CORS behavior for HTTP services.
|
|
// Used to control cross-origin requests from browsers.
|
|
type CORSConfig struct {
|
|
// AllowedOrigins lists domains allowed to make cross-origin requests.
|
|
// Use []string{"*"} for open access (dev/staging), specific domains for production.
|
|
// Example: []string{"https://app.example.com", "https://admin.example.com"}
|
|
AllowedOrigins []string
|
|
|
|
// AllowedMethods lists HTTP methods that can be used in cross-origin requests.
|
|
// Example: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}
|
|
AllowedMethods []string
|
|
|
|
// AllowedHeaders lists request headers that can be included in cross-origin requests.
|
|
// Must include headers used by services (Authorization, X-Request-ID, etc.)
|
|
AllowedHeaders []string
|
|
|
|
// ExposedHeaders lists response headers that the browser can expose to JavaScript.
|
|
// Useful for pagination headers, custom metadata, etc.
|
|
ExposedHeaders []string
|
|
|
|
// AllowCredentials controls whether browsers can send credentials (cookies, auth headers)
|
|
// in cross-origin requests. MUST be false when AllowedOrigins is "*".
|
|
AllowCredentials bool
|
|
|
|
// MaxAge specifies how long (in seconds) browsers can cache preflight responses.
|
|
// Reduces OPTIONS requests for the same resource.
|
|
MaxAge int
|
|
}
|
|
|
|
// DefaultCORSConfig returns sensible defaults for services.
|
|
// Designed for local development and staging environments.
|
|
//
|
|
// Defaults:
|
|
// - AllowedOrigins: ["*"] (override in production to specific domains)
|
|
// - AllowedMethods: GET, POST, PUT, PATCH, DELETE, OPTIONS
|
|
// - AllowedHeaders: ["*"] (allows any header - simplest for development)
|
|
// - ExposedHeaders: Link (for pagination)
|
|
// - AllowCredentials: false (required when AllowedOrigins is "*")
|
|
// - MaxAge: 300 seconds (5 minutes)
|
|
//
|
|
// Production services should override AllowedOrigins with specific domains,
|
|
// set AllowCredentials: true if needed, and optionally restrict AllowedHeaders.
|
|
func DefaultCORSConfig() CORSConfig {
|
|
return CORSConfig{
|
|
AllowedOrigins: []string{"*"},
|
|
AllowedMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"},
|
|
AllowedHeaders: []string{"*"},
|
|
ExposedHeaders: []string{"Link"},
|
|
AllowCredentials: false,
|
|
MaxAge: 300,
|
|
}
|
|
}
|
|
|
|
// CORS returns middleware that handles CORS headers for cross-origin requests.
|
|
// Uses github.com/go-chi/cors under the hood for RFC compliance.
|
|
//
|
|
// The middleware:
|
|
// - Handles preflight OPTIONS requests automatically
|
|
// - Sets Access-Control-* headers on actual requests
|
|
// - Validates origins against AllowedOrigins
|
|
// - Caches preflight responses according to MaxAge
|
|
//
|
|
// Usage:
|
|
//
|
|
// r := chi.NewRouter()
|
|
// r.Use(middleware.CORS(middleware.DefaultCORSConfig()))
|
|
//
|
|
// Production example:
|
|
//
|
|
// cfg := middleware.CORSConfig{
|
|
// AllowedOrigins: []string{"https://app.example.com"},
|
|
// AllowedMethods: []string{"GET", "POST", "PUT", "DELETE"},
|
|
// AllowedHeaders: []string{"Content-Type", "Authorization"},
|
|
// AllowCredentials: true,
|
|
// MaxAge: 600,
|
|
// }
|
|
// r.Use(middleware.CORS(cfg))
|
|
func CORS(cfg CORSConfig) func(http.Handler) http.Handler {
|
|
c := cors.New(cors.Options{
|
|
AllowedOrigins: cfg.AllowedOrigins,
|
|
AllowedMethods: cfg.AllowedMethods,
|
|
AllowedHeaders: cfg.AllowedHeaders,
|
|
ExposedHeaders: cfg.ExposedHeaders,
|
|
AllowCredentials: cfg.AllowCredentials,
|
|
MaxAge: cfg.MaxAge,
|
|
})
|
|
|
|
return c.Handler
|
|
}
|