CORS Middleware
The CORS (Cross-Origin Resource Sharing) middleware handles cross-origin resource sharing, allowing you to control which domains can access your API resources.
Usage
Basic Usage
import (
"go-slim.dev/slim"
"go-slim.dev/slim/middleware"
)
func main() {
s := slim.New()
// Use default configuration
s.Use(middleware.CORS())
s.GET("/api/users", func(c slim.Context) error {
return c.JSON(200, map[string]string{"message": "Hello"})
})
s.Start(":8080")
}
Custom Configuration
s := slim.New()
s.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: []string{"https://example.com", "https://app.example.com"},
AllowMethods: []string{"GET", "POST", "PUT", "DELETE"},
AllowHeaders: []string{"Content-Type", "Authorization"},
AllowCredentials: true,
ExposeHeaders: []string{"X-Request-ID"},
MaxAge: 3600,
}))
Configuration Options
CORSConfig
type CORSConfig struct {
// AllowOrigins defines a list of origins that may access the resource
// Optional. Default value []string{"*"}
AllowOrigins []string
// AllowOriginFunc is a custom function to validate the origin
// If this option is set, AllowOrigins is ignored
// Optional
AllowOriginFunc func(origin string) (bool, error)
// AllowMethods defines a list methods allowed when accessing the resource
// Used in response to a preflight request
// Optional. Default value includes common methods
AllowMethods []string
// AllowHeaders defines a list of request headers that can be used
// Used in response to a preflight request
// Optional. Default value []string{}
AllowHeaders []string
// AllowCredentials indicates whether the response can be exposed
// when the credentials flag is true
// Optional. Default value false
AllowCredentials bool
// ExposeHeaders defines the whitelist headers that clients are allowed to access
// Optional. Default value []string{}
ExposeHeaders []string
// MaxAge indicates how long (in seconds) the results of a preflight
// request can be cached
// Optional. Default value 0
MaxAge int
}
Examples
1. Allow All Origins (Development)
s.Use(middleware.CORS())
The default configuration allows all origins (AllowOrigins: []string{"*"}), suitable for development environments.
2. Restrict Specific Domains
s.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: []string{
"https://example.com",
"https://app.example.com",
},
}))
3. Use Wildcard Patterns
s.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: []string{
"https://*.example.com", // Allow all subdomains of example.com
"http://localhost:*", // Allow localhost on all ports
},
}))
4. Custom Origin Validation Function
s.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowOriginFunc: func(origin string) (bool, error) {
// Custom logic, e.g., query from database
allowedOrigins := []string{
"https://example.com",
"https://app.example.com",
}
for _, allowed := range allowedOrigins {
if origin == allowed {
return true, nil
}
}
return false, nil
},
}))
5. Support Credentials (Cookies)
s.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: []string{"https://example.com"},
AllowCredentials: true,
AllowHeaders: []string{"Content-Type", "Authorization"},
}))
Note: When AllowCredentials: true, AllowOrigins cannot be set to ["*"]. You must specify concrete domain names.
6. Complete Configuration Example
s.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: []string{
"https://example.com",
"https://app.example.com",
},
AllowMethods: []string{
"GET",
"POST",
"PUT",
"PATCH",
"DELETE",
"OPTIONS",
},
AllowHeaders: []string{
"Origin",
"Content-Type",
"Accept",
"Authorization",
"X-Request-ID",
},
ExposeHeaders: []string{
"X-Request-ID",
"X-Response-Time",
},
AllowCredentials: true,
MaxAge: 3600, // 1 hour
}))
How It Works
Simple Requests
For simple requests, the CORS middleware:
- Checks the
Originheader - Validates if the origin is in the allow list
- If allowed, sets the
Access-Control-Allow-Originresponse header - If
AllowCredentialsis configured, sets the corresponding response header - Continues processing the request
Preflight Requests
For preflight requests (HTTP OPTIONS), the CORS middleware:
- Checks the
Originheader - Validates if the origin is in the allow list
- Sets
Access-Control-Allow-Origin - Sets
Access-Control-Allow-Methods - Sets
Access-Control-Allow-Headers - If
MaxAgeis configured, setsAccess-Control-Max-Age - Returns
204 No Contentstatus code
Default Configuration
CORSConfig{
AllowOrigins: []string{"*"},
AllowMethods: []string{
"GET",
"HEAD",
"PUT",
"PATCH",
"POST",
"DELETE",
},
AllowHeaders: []string{},
AllowCredentials: false,
ExposeHeaders: []string{},
MaxAge: 0,
}
Best Practices
1. Restrict Origins in Production
// Development environment
if os.Getenv("ENV") == "development" {
s.Use(middleware.CORS())
} else {
// Production environment
s.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: []string{
"https://yourdomain.com",
"https://app.yourdomain.com",
},
AllowCredentials: true,
}))
}
2. Use Environment Variables
allowedOrigins := strings.Split(os.Getenv("ALLOWED_ORIGINS"), ",")
s.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: allowedOrigins,
}))
3. Limit Exposed Headers
Only expose headers that clients actually need:
s.Use(middleware.CORSWithConfig(middleware.CORSConfig{
ExposeHeaders: []string{
"X-Request-ID",
"X-Total-Count", // May be needed for pagination
},
}))
4. Set Reasonable MaxAge
Setting a reasonable cache time can reduce the number of preflight requests:
s.Use(middleware.CORSWithConfig(middleware.CORSConfig{
MaxAge: 86400, // 24 hours
}))
Security Considerations
-
Never use
AllowOrigins: ["*"]in production - this allows any website to access your API -
Use
AllowCredentials: truewith caution - ensure you understand the security implications -
Limit
AllowMethods- only allow necessary HTTP methods -
Limit
AllowHeaders- only allow necessary request headers -
Use HTTPS - avoid transmitting sensitive information over insecure connections
Common Questions
Q: Why is my CORS request failing?
A: Check the following:
- Is the CORS middleware properly configured on the server?
- Does
AllowOriginsinclude the client's domain? - If using credentials (Cookies), is
AllowCredentials: trueset? - Are
AllowHeadersandAllowMethodscorrectly configured?
Q: What is a preflight request?
A: A preflight request is an OPTIONS request automatically sent by the browser before certain cross-origin requests to check if the server allows the actual request.
Q: Can AllowOrigins: ["*"] and AllowCredentials: true be used together?
A: No. For security reasons, when credentials are enabled, you must specify concrete origins, not the wildcard *.