Documentation
¶
Overview ¶
middleware/compress.go
middleware/contenttype.go
middleware/cors.go
middleware/security.go
middleware/sizelimit.go
Index ¶
- func CORS(opts CORSOptions) func(next http.Handler) http.Handler
- func CORSFromConfig(coreCfg *config.CoreConfig) func(next http.Handler) http.Handler
- func CORSPermissive() func(next http.Handler) http.Handler
- func Compress(level int) func(next http.Handler) http.Handler
- func CompressFromConfig(coreCfg *config.CoreConfig, logger Logger) func(next http.Handler) http.Handler
- func CompressWithLogger(level int, logger Logger) func(next http.Handler) http.Handler
- func CompressWithTypes(level int, types ...string) func(next http.Handler) http.Handler
- func CompressWithTypesAndLogger(level int, logger Logger, types ...string) func(next http.Handler) http.Handler
- func LimitBodySize(maxBytes int64) func(next http.Handler) http.Handler
- func MethodNotAllowedHandler(logger *zap.Logger) http.HandlerFunc
- func NotFoundHandler(logger *zap.Logger) http.HandlerFunc
- func RequireJSON() func(next http.Handler) http.Handler
- func SecureDefaults() func(next http.Handler) http.Handler
- func SecurityHeaders(opts SecurityHeadersOptions) func(next http.Handler) http.Handler
- func SecurityHeadersFromConfig(coreCfg *config.CoreConfig) func(next http.Handler) http.Handler
- type CORSOptions
- type Logger
- type SecurityHeadersOptions
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CORS ¶ added in v0.1.19
func CORS(opts CORSOptions) func(next http.Handler) http.Handler
CORS returns a middleware with the specified CORS options. Use this when you need custom CORS settings not driven by config.
Panics immediately (at middleware construction time, not at first request) if AllowCredentials is true and AllowedOrigins contains "*", as this combination is rejected by browsers and indicates a misconfiguration. Also panics if MaxAge exceeds 1 week (604800 seconds). This ensures misconfigurations are caught during application startup when building the router, not at runtime.
Example:
r.Use(middleware.CORS(middleware.CORSOptions{
AllowedOrigins: []string{"https://app.example.com"},
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE"},
AllowedHeaders: []string{"Accept", "Authorization", "Content-Type"},
AllowCredentials: true,
MaxAge: 600,
}))
func CORSFromConfig ¶
CORSFromConfig returns a middleware that applies CORS behavior based on the given CoreConfig's CORS section.
If coreCfg is nil or coreCfg.CORS.EnableCORS is false, it returns an identity middleware that does nothing. This makes it safe to unconditionally call:
r.Use(middleware.CORSFromConfig(coreCfg))
and let config decide whether CORS is active.
Note: Passing nil config is supported but discouraged. If you need CORS but don't have a CoreConfig, use the CORS() function with explicit options instead.
func CORSPermissive ¶ added in v0.1.19
CORSPermissive returns a permissive CORS middleware suitable for development or internal APIs where security restrictions are not needed.
Policy:
- Allow all origins ("*")
- Allow GET, POST, PUT, PATCH, DELETE, OPTIONS
- Allow common headers including Authorization
- No credentials (cannot use credentials with "*" origins)
- 5 minute preflight cache
WARNING: Do not use in production with sensitive APIs. Use CORS() or CORSFromConfig() with specific allowed origins instead.
func Compress ¶ added in v0.1.19
Compress returns a compression middleware with the specified compression level.
Level ranges from 1 (best speed) to 9 (best compression). Level 5 is a good balance between speed and compression ratio. Levels outside 1-9 are clamped to the nearest valid value.
Compression supports gzip and deflate encodings based on the client's Accept-Encoding header.
Example:
r.Use(middleware.Compress(5))
func CompressFromConfig ¶ added in v0.1.19
func CompressFromConfig(coreCfg *config.CoreConfig, logger Logger) func(next http.Handler) http.Handler
CompressFromConfig returns a compression middleware based on the CoreConfig.
If coreCfg.EnableCompression is false, it returns an identity middleware that does nothing. This makes it safe to unconditionally call:
r.Use(middleware.CompressFromConfig(coreCfg, nil))
and let config decide whether compression is active. The compression level is determined by coreCfg.CompressionLevel (1-9, default 5).
Compression supports gzip and deflate encodings based on the client's Accept-Encoding header.
Note: The compression level is validated in config.validateCoreConfig(). Invalid values reaching this function indicate a bug in config validation.
func CompressWithLogger ¶ added in v0.1.19
CompressWithLogger is like Compress but logs a warning if the level is clamped.
func CompressWithTypes ¶ added in v0.1.19
CompressWithTypes returns a compression middleware that only compresses responses with the specified content types. Levels outside 1-9 are clamped to the nearest valid value.
Example:
r.Use(middleware.CompressWithTypes(5, "text/html", "text/css", "application/json"))
func CompressWithTypesAndLogger ¶ added in v0.1.19
func CompressWithTypesAndLogger(level int, logger Logger, types ...string) func(next http.Handler) http.Handler
CompressWithTypesAndLogger is like CompressWithTypes but logs a warning if the level is clamped.
func LimitBodySize ¶
LimitBodySize returns a middleware that limits the size of the request body to maxBytes. If maxBytes <= 0, it is a no-op and does not wrap the body.
This should typically be applied early in the middleware chain to prevent handlers from processing huge bodies.
func MethodNotAllowedHandler ¶
func MethodNotAllowedHandler(logger *zap.Logger) http.HandlerFunc
MethodNotAllowedHandler returns a handler that logs a 405 and returns a JSON error body. It is designed to be passed directly to chi.Router.MethodNotAllowed(..).
func NotFoundHandler ¶
func NotFoundHandler(logger *zap.Logger) http.HandlerFunc
NotFoundHandler returns a handler that logs a 404 and returns a JSON error body. It is designed to be passed directly to chi.Router.NotFound(..).
func RequireJSON ¶
RequireJSON returns a middleware that ensures requests have a JSON Content-Type, typically "application/json" or something ending in "+json", e.g. "application/problem+json".
If the Content-Type is missing or not JSON, it returns 415 Unsupported Media Type with a JSON error body.
func SecureDefaults ¶ added in v0.1.34
SecureDefaults returns middleware with secure default headers. This is a convenience function equivalent to:
SecurityHeaders(DefaultSecurityHeadersOptions())
Use this when you want good security defaults without configuration.
func SecurityHeaders ¶ added in v0.1.34
func SecurityHeaders(opts SecurityHeadersOptions) func(next http.Handler) http.Handler
SecurityHeaders returns middleware that sets common security headers. Uses the provided options to configure which headers are set.
Example:
r.Use(middleware.SecurityHeaders(middleware.DefaultSecurityHeadersOptions()))
Or with custom options:
r.Use(middleware.SecurityHeaders(middleware.SecurityHeadersOptions{
XFrameOptions: "DENY",
XContentTypeOptions: "nosniff",
HSTSMaxAge: 63072000, // 2 years
}))
func SecurityHeadersFromConfig ¶ added in v0.1.34
SecurityHeadersFromConfig returns middleware configured from CoreConfig.
If security headers are disabled in config (enable_security_headers = false), returns a no-op middleware. This makes it safe to unconditionally use:
r.Use(middleware.SecurityHeadersFromConfig(coreCfg))
The middleware respects the production/development environment:
- HSTS is only sent for HTTPS requests
- In dev mode with use_https=false, HSTS is effectively disabled
Types ¶
type CORSOptions ¶ added in v0.1.19
type CORSOptions struct {
// AllowedOrigins is a list of origins a cross-domain request can be executed from.
// Use ["*"] to allow any origin, or specify exact origins like ["https://example.com"].
// IMPORTANT: Using ["*"] with AllowCredentials=true is not allowed by browsers.
AllowedOrigins []string
// AllowedMethods is a list of methods the client is allowed to use.
// Default: ["GET", "POST", "OPTIONS"]
AllowedMethods []string
// AllowedHeaders is a list of headers the client is allowed to use.
// Default: ["Accept", "Authorization", "Content-Type"]
AllowedHeaders []string
// ExposedHeaders is a list of headers that are safe to expose to the client.
ExposedHeaders []string
// AllowCredentials indicates whether the request can include credentials like
// cookies, HTTP authentication or client side SSL certificates.
// Cannot be true when AllowedOrigins is ["*"].
// See the security considerations above before enabling this.
AllowCredentials bool
// MaxAge indicates how long (in seconds) the results of a preflight request
// can be cached. Default: 300 (5 minutes)
MaxAge int
}
CORSOptions defines CORS policy settings.
Security Considerations:
When AllowCredentials is true, the browser will include cookies and authentication headers in cross-origin requests. This has significant security implications:
NEVER use AllowCredentials with wildcard origins (["*"]). The browser will reject this combination, and WAFFLE's config validation enforces it.
Only allow origins you explicitly trust. Each allowed origin can make authenticated requests on behalf of your users.
Consider using SameSite cookie attributes alongside CORS for defense in depth against CSRF attacks.
If you don't need credentials (cookies/auth), keep AllowCredentials false to reduce your attack surface.
type Logger ¶ added in v0.1.19
Logger is a minimal interface for logging warnings during middleware setup. This avoids coupling to zap while allowing optional warning logs.
type SecurityHeadersOptions ¶ added in v0.1.34
type SecurityHeadersOptions struct {
// XFrameOptions controls whether the page can be embedded in iframes.
// Values: "DENY", "SAMEORIGIN", or "ALLOW-FROM uri"
// Default: "SAMEORIGIN"
// Set to empty string to disable this header.
XFrameOptions string
// XContentTypeOptions prevents MIME type sniffing.
// Should always be "nosniff" unless you have a specific reason to disable.
// Default: "nosniff"
// Set to empty string to disable this header.
XContentTypeOptions string
// ReferrerPolicy controls how much referrer information is sent.
// Common values:
// - "no-referrer" - Never send referrer
// - "origin" - Send only the origin (scheme + host)
// - "strict-origin-when-cross-origin" - Full URL to same origin, origin only to others
// Default: "strict-origin-when-cross-origin"
// Set to empty string to disable this header.
ReferrerPolicy string
// XSSProtection enables/configures the browser's XSS filter.
// Note: This is deprecated in modern browsers in favor of CSP.
// Values: "0" (disable), "1" (enable), "1; mode=block"
// Default: "1; mode=block"
// Set to empty string to disable this header.
XSSProtection string
// HSTSMaxAge sets the Strict-Transport-Security max-age in seconds.
// Only sent when the request is over HTTPS.
// Default: 31536000 (1 year)
// Set to 0 to disable HSTS.
HSTSMaxAge int
// HSTSIncludeSubDomains adds includeSubDomains to the HSTS header.
// Default: true
HSTSIncludeSubDomains bool
// HSTSPreload adds the preload directive to HSTS.
// Only enable if you've submitted your domain to the HSTS preload list.
// Default: false
HSTSPreload bool
// ContentSecurityPolicy sets the Content-Security-Policy header.
// This is powerful but complex - misconfiguration can break your site.
// Default: empty (not set)
// Example: "default-src 'self'; script-src 'self' 'unsafe-inline'"
ContentSecurityPolicy string
// PermissionsPolicy (formerly Feature-Policy) controls browser features.
// Default: empty (not set)
// Example: "geolocation=(), microphone=(), camera=()"
PermissionsPolicy string
}
SecurityHeadersOptions configures the security headers middleware.
All headers have sensible defaults that provide good security without breaking most applications. Only customize if you have specific needs.
func DefaultSecurityHeadersOptions ¶ added in v0.1.34
func DefaultSecurityHeadersOptions() SecurityHeadersOptions
DefaultSecurityHeadersOptions returns options with secure defaults suitable for most web applications.