CORS
CORS is a middleware that handles Cross-Origin Resource Sharing (CORS) requests. It allows you to specify which origins are permitted to access your resources, as well as which HTTP methods and headers are allowed.
This middleware is converted from Echo's CORS middleware
mcors "github.com/rakunlabs/ada/middleware/cors"Add middleware to directly mux, group or handler; usually placed at the top of the middleware chain:
mcors.Middleware()Configuration
You can configure the middleware using mcors.WithConfig() option.
mcors.Middleware(
mcors.WithConfig(mcors.Cors{
AllowOrigins: []string{"https://example.com", "https://*.example.com"},
AllowMethods: []string{"GET", "POST", "PUT", "DELETE"},
AllowHeaders: []string{"Content-Type", "Authorization"},
AllowCredentials: true,
ExposeHeaders: []string{"X-Custom-Header"},
MaxAge: 3600,
}),
)Configuration Options
Options docs generated by AI.
AllowOrigins
Determines the value of the Access-Control-Allow-Origin response header. This header defines a list of origins that may access the resource.
- Type:
[]string - Default:
[]string{"*"} - Supports wildcards:
*(any characters) and?(single character)
Examples:
// Allow all origins (default)
AllowOrigins: []string{"*"}
// Allow specific domains
AllowOrigins: []string{"https://example.com", "https://api.example.com"}
// Allow subdomains using wildcards
AllowOrigins: []string{"https://*.example.com"}
// Mix specific and wildcard patterns
AllowOrigins: []string{"https://example.com", "https://*.trusted.com"}Security Warning
Use extreme caution when handling origins and carefully validate any logic. Remember that attackers may register hostile domain names. See Exploiting CORS Misconfigurations.
MDN Reference: Access-Control-Allow-Origin
AllowMethods
Determines the value of the Access-Control-Allow-Methods response header. This header specifies the list of methods allowed when accessing the resource in response to a preflight request.
- Type:
[]string - Default:
[]string{"GET", "HEAD", "PUT", "PATCH", "POST", "DELETE"}
Example:
AllowMethods: []string{"GET", "POST", "PUT", "DELETE"}MDN Reference: Access-Control-Allow-Methods
AllowHeaders
Determines the value of the Access-Control-Allow-Headers response header. This header is used in response to a preflight request to indicate which HTTP headers can be used when making the actual request.
- Type:
[]string - Default:
[]string{}(empty, will echo back requested headers)
Example:
AllowHeaders: []string{"Content-Type", "Authorization", "X-Request-ID"}If left empty, the middleware will automatically allow headers requested by the client in the preflight request.
MDN Reference: Access-Control-Allow-Headers
AllowCredentials
Determines the value of the Access-Control-Allow-Credentials response header. This header indicates whether the response can be exposed when the credentials mode is true (cookies, authorization headers, or TLS client certificates).
- Type:
bool - Default:
false
Example:
AllowCredentials: trueSecurity Warning
Avoid using AllowCredentials: true with AllowOrigins: []string{"*"}. This is a security vulnerability. See Exploiting CORS Misconfigurations.
MDN Reference: Access-Control-Allow-Credentials
UnsafeWildcardOriginWithAllowCredentials
⚠️ UNSAFE/INSECURE: Allows wildcard * origin to be used with AllowCredentials flag. When enabled, any origin is considered allowed and sent back to the client with the Access-Control-Allow-Origin header.
- Type:
bool - Default:
false
Security Warning
This is INSECURE and potentially leads to cross-origin attacks. Only use this if you fully understand the security implications.
Example:
// NOT RECOMMENDED - Security Risk!
AllowOrigins: []string{"*"},
AllowCredentials: true,
UnsafeWildcardOriginWithAllowCredentials: true,ExposeHeaders
Determines the value of Access-Control-Expose-Headers, which defines a list of headers that clients are allowed to access from the response.
- Type:
[]string - Default:
[]string{}(empty, header not set)
Example:
ExposeHeaders: []string{"X-Request-ID", "X-Response-Time"}By default, only these CORS-safelisted response headers are exposed:
Cache-ControlContent-LanguageContent-TypeExpiresLast-ModifiedPragma
Use this option to expose additional headers.
MDN Reference: Access-Control-Expose-Headers
MaxAge
Determines the value of the Access-Control-Max-Age response header. This header indicates how long (in seconds) the results of a preflight request can be cached.
- Type:
int - Default:
0(header not sent) - Negative value: Sends
"0"which instructs browsers not to cache
Example:
MaxAge: 3600 // Cache preflight for 1 hourMDN Reference: Access-Control-Max-Age
Complete Example
package main
import (
"net/http"
"github.com/rakunlabs/ada"
mcors "github.com/rakunlabs/ada/middleware/cors"
)
func main() {
mux := ada.New()
// Add CORS middleware with full configuration
mux.Use(mcors.Middleware(
mcors.WithConfig(mcors.Cors{
AllowOrigins: []string{"https://example.com", "https://*.example.com"},
AllowMethods: []string{http.MethodGet, http.MethodPost, http.MethodPut, http.MethodDelete},
AllowHeaders: []string{"Content-Type", "Authorization", "X-Request-ID"},
AllowCredentials: true,
ExposeHeaders: []string{"X-Response-Time", "X-Request-ID"},
MaxAge: 86400, // 24 hours
}),
))
mux.HandleFunc("/api/data", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"message": "CORS enabled!"}`))
})
http.ListenAndServe(":8080", mux)
}Common Scenarios
Development Environment (Allow All)
mcors.Middleware(
mcors.WithConfig(mcors.Cors{
AllowOrigins: []string{"*"},
AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowHeaders: []string{"*"},
}),
)Production with Specific Origins
mcors.Middleware(
mcors.WithConfig(mcors.Cors{
AllowOrigins: []string{"https://app.example.com", "https://admin.example.com"},
AllowMethods: []string{"GET", "POST", "PUT", "DELETE"},
AllowHeaders: []string{"Content-Type", "Authorization"},
AllowCredentials: true,
MaxAge: 3600,
}),
)Allow Subdomains
mcors.Middleware(
mcors.WithConfig(mcors.Cors{
AllowOrigins: []string{"https://*.example.com"},
AllowCredentials: true,
MaxAge: 7200,
}),
)How It Works
Preflight Requests
For complex requests, browsers send a preflight OPTIONS request before the actual request. The middleware handles these automatically:
Browser sends
OPTIONSrequest with:OriginheaderAccess-Control-Request-MethodheaderAccess-Control-Request-Headersheader (optional)
Middleware responds with appropriate CORS headers:
Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-HeadersAccess-Control-Max-Age
If the preflight is successful, browser sends the actual request
Simple Requests
For simple requests (GET, HEAD, or POST with simple headers), no preflight is required. The middleware adds appropriate CORS headers directly to the response.
Wildcard Pattern Matching
The middleware supports wildcard patterns in AllowOrigins:
*- matches any number of characters?- matches a single character
Examples:
https://*.example.com- matcheshttps://api.example.com,https://app.example.com, etc.https://api-?.example.com- matcheshttps://api-1.example.com,https://api-2.example.com, etc.
Patterns are converted to regular expressions internally for efficient matching.
Best Practices
Be Specific: Avoid using
*in production. List specific allowed origins.Credentials Security: Never combine
AllowOrigins: ["*"]withAllowCredentials: true.Minimize Allowed Methods: Only allow HTTP methods that your API actually uses.
Cache Preflight Results: Set
MaxAgeto reduce preflight requests and improve performance.Validate Origins Carefully: Remember that attackers can register malicious domains. Validate your origin patterns thoroughly.
Use HTTPS: Always use HTTPS in production, especially when
AllowCredentialsistrue.
Troubleshooting
CORS Error: Origin Not Allowed
Check that the origin in the browser request matches one of your AllowOrigins patterns exactly, including the protocol (https:// vs http://).
Credentials Request Failed
Ensure both conditions are met:
AllowCredentials: truein middleware configuration- Client-side request includes
credentials: 'include'(fetch) orwithCredentials: true(XMLHttpRequest) - Origin is explicitly listed (not
*)
Preflight Request Returns 204 but Actual Request Fails
Verify that your server handler doesn't return errors for the actual request. The middleware only handles CORS headers; your handler must also work correctly.