Skip to main content

Overview

The cors middleware handles Cross-Origin Resource Sharing (CORS), allowing your API to be safely accessed from different domains. It automatically handles preflight requests and sets the appropriate headers. Use it when you need:
  • API access from browser applications on different domains
  • Single-page applications calling your backend
  • Mobile apps using web views

Installation

import "github.com/go-mizu/mizu/middlewares/cors"

Quick Start

app := mizu.New()

// Allow all origins (development only)
app.Use(cors.AllowAll())

// Or allow specific origins
app.Use(cors.WithOrigins("https://example.com", "https://app.example.com"))

Configuration

Options

OptionTypeDefaultDescription
AllowOrigins[]string["*"]Allowed origins
AllowMethods[]string["GET", "POST", "HEAD"]Allowed HTTP methods
AllowHeaders[]string["Origin", "Content-Type", "Accept"]Allowed request headers
ExposeHeaders[]string[]Headers exposed to browser
AllowCredentialsboolfalseAllow credentials (cookies)
MaxAgetime.Duration0Preflight cache duration
AllowOriginFuncfunc(string) boolnilCustom origin validator
AllowPrivateNetworkboolfalseEnable Private Network Access

Examples

Allow All Origins (Development)

app.Use(cors.AllowAll())

Specific Origins

app.Use(cors.New(cors.Options{
    AllowOrigins: []string{
        "https://example.com",
        "https://admin.example.com",
    },
}))

With Credentials

app.Use(cors.New(cors.Options{
    AllowOrigins:     []string{"https://app.example.com"},
    AllowCredentials: true,
    AllowMethods:     []string{"GET", "POST", "PUT", "DELETE"},
    AllowHeaders:     []string{"Authorization", "Content-Type"},
}))

Custom Origin Validation

app.Use(cors.New(cors.Options{
    AllowOriginFunc: func(origin string) bool {
        // Allow all subdomains of example.com
        return strings.HasSuffix(origin, ".example.com")
    },
}))

Preflight Caching

app.Use(cors.New(cors.Options{
    AllowOrigins: []string{"https://example.com"},
    MaxAge:       12 * time.Hour, // Cache preflight for 12 hours
}))

API Reference

Functions

// New creates CORS middleware with options
func New(opts Options) mizu.Middleware

// AllowAll creates permissive CORS (development only)
func AllowAll() mizu.Middleware

// WithOrigins creates CORS allowing specific origins
func WithOrigins(origins ...string) mizu.Middleware

Technical Details

Implementation Overview

The CORS middleware implements the W3C Cross-Origin Resource Sharing specification by:
  1. Origin Validation: Checks incoming requests against allowed origins using either:
    • Static origin list (AllowOrigins)
    • Custom validation function (AllowOriginFunc)
    • Wildcard matching for development scenarios
  2. Header Management: Sets appropriate CORS headers based on configuration:
    • Access-Control-Allow-Origin: The allowed origin (specific or wildcard)
    • Access-Control-Allow-Methods: Permitted HTTP methods
    • Access-Control-Allow-Headers: Permitted request headers
    • Access-Control-Expose-Headers: Headers exposed to the client
    • Access-Control-Allow-Credentials: Credential support flag
    • Access-Control-Max-Age: Preflight cache duration in seconds
    • Vary: Origin: Added when using specific origins to ensure proper caching
  3. Preflight Handling: Automatically responds to OPTIONS requests with:
    • No content (204 status)
    • All necessary CORS headers
    • Optional Private Network Access support

Default Values

When options are not specified, the middleware uses these defaults:
  • AllowOrigins: ["*"] (all origins)
  • AllowMethods: ["GET", "POST", "HEAD"]
  • AllowHeaders: ["Origin", "Content-Type", "Accept"]
  • ExposeHeaders: [] (empty)
  • AllowCredentials: false
  • MaxAge: 0 (no caching)

Request Flow

  1. Extract Origin header from request
  2. If no origin header, skip CORS processing
  3. Validate origin against allowed list or function
  4. If origin not allowed, continue without CORS headers
  5. Set Access-Control-Allow-Origin header (wildcard or specific)
  6. Add Vary: Origin header when using specific origins
  7. Set credentials header if enabled
  8. Set expose headers if configured
  9. For OPTIONS requests (preflight):
    • Set methods and headers
    • Set max-age if configured
    • Handle Private Network Access if enabled
    • Return 204 No Content
  10. For regular requests, continue to next handler

Security Considerations

  1. Never use AllowAll() in production - It exposes your API to any origin
  2. Be careful with credentials - When AllowCredentials is true, you cannot use wildcard origins
  3. Validate origins - Use AllowOriginFunc for dynamic origin validation
  4. Limit exposed headers - Only expose headers that clients actually need

Best Practices

  • Use specific origins in production
  • Cache preflight requests with MaxAge to reduce OPTIONS requests
  • Combine with authentication middleware for protected endpoints
  • Use AllowPrivateNetwork only when needed for local network access

Testing

The CORS middleware includes comprehensive test coverage for all features and edge cases:
Test CaseDescriptionExpected Behavior
TestNew/allows matching originRequest with allowed originReturns 200 OK with Access-Control-Allow-Origin header set to the matching origin
TestNew/ignores non-matching originRequest with non-allowed originProcesses request normally but does not set CORS headers
TestNew/handles preflightOPTIONS request with originReturns 204 No Content with Access-Control-Allow-Methods and other preflight headers
TestNew/ignores requests without originRequest without Origin headerProcesses request normally without setting any CORS headers
TestAllowAllAllowAll() with any originSets Access-Control-Allow-Origin: * for any origin
TestWithOrigins/http://a.comWithOrigins() with allowed originSets Access-Control-Allow-Origin to the specific allowed origin
TestWithOrigins/http://b.comWithOrigins() with another allowed originSets Access-Control-Allow-Origin to the specific allowed origin
TestWithOrigins/http://c.comWithOrigins() with non-allowed originDoes not set Access-Control-Allow-Origin header
TestNew_AllowCredentialsCredentials enabled with specific originSets Access-Control-Allow-Credentials: true and specific origin (not wildcard)
TestNew_ExposeHeadersCustom expose headers configuredSets Access-Control-Expose-Headers with comma-separated header list
TestNew_MaxAgeMaxAge set to 12 hoursSets Access-Control-Max-Age: 43200 on preflight requests
TestNew_AllowOriginFunc/http://example.comCustom origin validator (exact match)Allows the origin when validation function returns true
TestNew_AllowOriginFunc/http://api.example.comCustom origin validator (subdomain)Allows subdomain when validation function returns true
TestNew_AllowOriginFunc/http://other.comCustom origin validator (non-matching)Denies origin when validation function returns false
TestNew_PrivateNetworkPrivate Network Access enabledSets Access-Control-Allow-Private-Network: true when requested
TestNew_VaryHeaderSpecific origin configuredAdds Vary: Origin header to ensure proper caching
  • cors2 - Enhanced CORS with additional features
  • secure - HTTPS enforcement
  • helmet - Security headers