Documentation
¶
Index ¶
- func CORS(options ...Option) (func(http.Handler) http.Handler, error)
- func MustCORS(options ...Option) func(http.Handler) http.Handler
- func NoStoreAPIResponses(next http.Handler) http.Handler
- func Recovery(logger *slog.Logger) func(http.Handler) http.Handler
- func RequestScope(next http.Handler) http.Handler
- func SecurityHeaders(next http.Handler) http.Handler
- func TenantFromHeader(headerName string) func(http.Handler) http.Handler
- func TenantFromSubdomain(baseDomain string) func(http.Handler) http.Handler
- func WAF(cfg WAFConfig) func(http.Handler) http.Handler
- type Option
- type WAFConfig
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func MustCORS ¶
MustCORS panics when CORS configuration is invalid, for applications that prefer configuration failures during startup.
func NoStoreAPIResponses ¶ added in v0.9.0
NoStoreAPIResponses disables caching for API paths under /api/.
func Recovery ¶
Recovery catches panics that escape from downstream handlers and middleware, converts them into a 500 response, and logs the panic with its stack trace.
func RequestScope ¶
RequestScope provisions a pooled xctx.RequestScope for every HTTP request. It MUST be the outermost middleware in the chain.
func SecurityHeaders ¶
SecurityHeaders applies a conservative set of HTTP hardening headers to every response. The set is deliberately narrow: it improves defaults without being so opinionated that it breaks legitimate same-host UI such as Scalar docs, GraphiQL, or embedded consoles.
Content-Security-Policy is intentionally NOT set. CSP is genuinely application-specific — a policy that works for a JSON API breaks a dashboard with inline styles — and silently shipping a default has caused more outages than it has prevented. Applications that serve HTML should add their own CSP middleware after this one.
Zero-allocation contract: net/http pre-sizes the response header map, so each Set is a map write without growth. No allocation on the fast path.
func TenantFromHeader ¶
TenantFromHeader reads a tenant identifier from a request header and attaches it to the execution context.
This is the correct place for tenant extraction on HTTP paths. The header is presumed to have been set by an upstream trusted authority: a gateway, a service mesh, or an authentication middleware that has already verified the caller's claims and rewritten the request.
This middleware deliberately does NOT trust a tenant id supplied in the request body. Placing tenant selection under client control is an authorization bypass in any multi-tenant system. When the tenant comes from verified JWT claims, do not use this middleware — set the tenant on the context inside the authentication middleware instead.
Use this middleware when:
- the service sits behind a trusted proxy that sets X-Tenant-ID
- a batch or internal service invocation carries the tenant in a well-known header
- local development needs to simulate a specific tenant
Do not use this middleware when the tenant is derived from a verified claim; extract the claim in the authentication middleware and call xctx.WithTenantID there.
Zero-allocation contract: the fast path does one header lookup and one field write inside the pooled scope. No allocation.
func TenantFromSubdomain ¶
TenantFromSubdomain extracts the tenant identifier from the request's leftmost subdomain label and attaches it to the context.
Example: acme.api.example.com → "acme"
This is a common SaaS pattern where each tenant gets a DNS alias. It is a shape-based extraction: the middleware does not verify that the subdomain corresponds to a real tenant — downstream actions validate that. Like TenantFromHeader, it assumes the deployment terminates at a trusted edge that controls DNS.
The baseDomain argument is not consulted at request time; it exists only to make the deployment intent explicit at the call site and to allow future validation. Pass an empty string for a purely local setup.
Types ¶
type Option ¶
type Option func(*corsConfig) error
Option configures CORS middleware.
func WithCredentials ¶
func WithCredentials() Option
WithCredentials enables Access-Control-Allow-Credentials. It cannot be used with a wildcard origin.
func WithEnv ¶
func WithEnv() Option
WithEnv reads CORS_ORIGINS, CORS_HEADERS, CORS_METHODS, CORS_EXPOSED, CORS_MAX_AGE, and CORS_CREDENTIALS from the process environment. It is evaluated when CORS is constructed, not on each request.
func WithExposedHeaders ¶
WithExposedHeaders sets response headers visible to browser JavaScript.
func WithHeaders ¶
WithHeaders sets allowed request headers for preflight requests.
func WithMaxAge ¶
WithMaxAge sets the preflight cache lifetime in seconds.
func WithMethods ¶
WithMethods overrides the methods advertised for preflight requests.
func WithOrigins ¶
WithOrigins sets the allowed origins. Use "*" to allow any origin. Wildcard origins cannot be combined with credentials.