package middleware import ( "github.com/gin-gonic/gin" ) // CORSConfig holds the configuration for the CORS middleware type CORSConfig struct { AllowedOrigins []string AllowedMethods []string AllowedHeaders []string AllowCredentials bool MaxAge int } // DefaultCORSConfig returns the default CORS configuration func DefaultCORSConfig() *CORSConfig { return &CORSConfig{ AllowedOrigins: []string{"*"}, AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"}, AllowedHeaders: []string{"Content-Type", "Authorization", "X-Requested-With", "Accept", "Origin"}, AllowCredentials: false, MaxAge: 86400, // 24 hours } } // CORS returns a Gin middleware handler for CORS (Cross-Origin Resource Sharing) func CORS() gin.HandlerFunc { return CORSWithConfig(DefaultCORSConfig()) } // CORSWithConfig returns a Gin middleware handler for CORS with custom configuration func CORSWithConfig(config *CORSConfig) gin.HandlerFunc { return func(c *gin.Context) { origin := c.GetHeader("Origin") // Check if the origin is allowed if len(config.AllowedOrigins) > 0 && config.AllowedOrigins[0] != "*" { allowed := false for _, allowedOrigin := range config.AllowedOrigins { if origin == allowedOrigin { allowed = true break } } if !allowed { c.AbortWithStatusJSON(403, gin.H{ "error": "origin not allowed", }) return } } // Set CORS headers if len(config.AllowedOrigins) > 0 { if config.AllowedOrigins[0] == "*" { c.Header("Access-Control-Allow-Origin", "*") } else { c.Header("Access-Control-Allow-Origin", origin) } } c.Header("Access-Control-Allow-Methods", joinStringSlice(config.AllowedMethods, ", ")) c.Header("Access-Control-Allow-Headers", joinStringSlice(config.AllowedHeaders, ", ")) if config.AllowCredentials { c.Header("Access-Control-Allow-Credentials", "true") } c.Header("Access-Control-Max-Age", stringFromInt(config.MaxAge)) // Handle preflight requests if c.Request.Method == "OPTIONS" { c.AbortWithStatus(204) return } c.Next() } } // Helper function to join a slice of strings func joinStringSlice(slice []string, sep string) string { if len(slice) == 0 { return "" } result := slice[0] for i := 1; i < len(slice); i++ { result += sep + slice[i] } return result } // Helper function to convert int to string func stringFromInt(n int) string { if n == 0 { return "" } return string(rune('0'+n%10)) + stringFromInt(n/10) }