Documentation
¶
Overview ¶
Package router provides an HTTP router for the Nucleus framework, built on top of Go's standard net/http.ServeMux (Go 1.22+). It includes a default middleware stack, response helpers, CSRF protection, and request binding with validation.
Index ¶
- Variables
- func Bind(r *http.Request, v interface{}) error
- func BindForm(r *http.Request, v interface{}) error
- func BindMax(r *http.Request, v interface{}, maxBytes int64) error
- func CORSMiddleware(opts CORSOptions) func(http.Handler) http.Handler
- func CSRFMiddleware(opts CSRFOptions) func(http.Handler) http.Handler
- func CSRFToken(r *http.Request) string
- func Compress(level int) func(http.Handler) http.Handler
- func ContextHandler(handlers ...Handler) http.HandlerFunc
- func Created(w http.ResponseWriter, data interface{})
- func DefaultStack(logger *slog.Logger, opts *routerOpts) []func(http.Handler) http.Handler
- func Error(w http.ResponseWriter, r *http.Request, err error, logger ...*slog.Logger)
- func GetReqID(ctx context.Context) string
- func IsWebSocketUpgrade(r *http.Request) bool
- func JSON(w http.ResponseWriter, status int, data interface{})
- func Matched(r *http.Request) bool
- func NewCSRFMiddleware(opts CSRFOptions) (func(http.Handler) http.Handler, error)
- func NoContent(w http.ResponseWriter)
- func Paginate(r *http.Request, defaultSize int) (page, pageSize int)
- func RateLimitFromPolicy(policy RateLimitPolicy) func(http.Handler) http.Handler
- func RateLimitMiddleware(opts RateLimitOptions) func(http.Handler) http.Handler
- func RealIP(next http.Handler) http.Handler
- func Recoverer(next http.Handler) http.Handler
- func RecovererWithLogger(logger *slog.Logger) func(http.Handler) http.Handler
- func RequestID(next http.Handler) http.Handler
- func RequestLogger(logger *slog.Logger) func(http.Handler) http.Handler
- func RouteFromContext(ctx context.Context) string
- func SecurityHeaders(next http.Handler) http.Handler
- func TelemetryMiddleware(next http.Handler) http.Handler
- func TimeoutMiddleware(timeout time.Duration) func(http.Handler) http.Handler
- func TimeoutMiddlewareWithExemptions(timeout time.Duration, exemptPrefixes []string) func(http.Handler) http.Handler
- type CORSOptions
- type CSRFOptions
- type Context
- func (c *Context) Bind(v interface{}) error
- func (c *Context) BindData(values map[string]interface{})
- func (c *Context) Data() map[string]interface{}
- func (c *Context) Download(path, filename string) error
- func (c *Context) File(path string) error
- func (c *Context) Form(name string) string
- func (c *Context) HTML(status int, templateName string, data map[string]interface{}) error
- func (c *Context) JSON(status int, data interface{}) error
- func (c *Context) Next() error
- func (c *Context) NoContent() error
- func (c *Context) Param(name string) string
- func (c *Context) Query(name string) string
- func (c *Context) Redirect(status int, location string) error
- func (c *Context) SessionDestroy() error
- func (c *Context) SessionGetBool(key string) bool
- func (c *Context) SessionGetInt(key string) int
- func (c *Context) SessionGetString(key string) string
- func (c *Context) SessionManager() *auth.SessionManager
- func (c *Context) SessionPutBool(key string, value bool) error
- func (c *Context) SessionPutInt(key string, value int) error
- func (c *Context) SessionPutString(key, value string) error
- func (c *Context) SessionRemove(key string) error
- func (c *Context) SessionRenewToken() error
- func (c *Context) Set(key string, value interface{})
- func (c *Context) T(key string, args ...any) string
- func (c *Context) Value(name string) string
- func (c *Context) XML(status int, data interface{}) error
- type ContextHandlerFunc
- type ContextOption
- type HTTPError
- type Handler
- type Middleware
- type Mux
- func (m *Mux) Delete(pattern string, handlers ...Handler)
- func (m *Mux) Get(pattern string, handlers ...Handler)
- func (m *Mux) Group(fn func(sub *Mux))
- func (m *Mux) Handle(pattern string, h http.Handler)
- func (m *Mux) HandleFunc(pattern string, h http.HandlerFunc)
- func (m *Mux) Mount(pattern string, handler http.Handler)
- func (m *Mux) Patch(pattern string, handlers ...Handler)
- func (m *Mux) Post(pattern string, handlers ...Handler)
- func (m *Mux) Put(pattern string, handlers ...Handler)
- func (m *Mux) Resource(pattern string, handlers ResourceHandlers)
- func (m *Mux) Route(pattern string, fn func(sub *Mux))
- func (m *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (m *Mux) SetHTMLTemplates(t *template.Template)
- func (m *Mux) SetSessionManager(sm *auth.SessionManager)
- func (m *Mux) Static(pattern, root string)
- func (m *Mux) Use(mws ...Middleware)
- func (m *Mux) Walk(fn func(method string, route string, handler http.Handler, ...) error) error
- func (m *Mux) With(mws ...Middleware) *Mux
- type Option
- func WithCORSCredentials(allow bool) Option
- func WithCORSOrigins(origins ...string) Option
- func WithCSRF(exemptPaths ...string) Option
- func WithCSRFInsecureCookie(insecure bool) Option
- func WithDevelopmentErrors(enabled bool) Option
- func WithHSTS(enabled bool) Option
- func WithRateLimit(requests int, window time.Duration) Option
- func WithRateLimitPolicy(policy RateLimitPolicy) Option
- func WithTimeout(seconds int) Option
- func WithTimeoutExempt(paths ...string) Option
- func WithTrustedProxies(proxies ...string) Option
- type RateLimitOptions
- type RateLimitPolicy
- type ResourceHandlers
- type RouteEntry
- type Router
- type WrapResponseWriter
- func (w *WrapResponseWriter) BytesWritten() int
- func (w *WrapResponseWriter) Flush()
- func (w *WrapResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error)
- func (w *WrapResponseWriter) Status() int
- func (w *WrapResponseWriter) Unwrap() http.ResponseWriter
- func (w *WrapResponseWriter) Write(b []byte) (int, error)
- func (w *WrapResponseWriter) WriteHeader(code int)
- func (w *WrapResponseWriter) WroteHeader() bool
Constants ¶
This section is empty.
Variables ¶
var ( ErrNilContextWriter = errors.New("router.Context: response writer is nil") ErrNilContextRequest = errors.New("router.Context: request is nil") ErrTemplateEngineNotSet = errors.New("router.Context: template engine is not configured") ErrTemplateNameRequired = errors.New("router.Context: template name is required") ErrFilePathRequired = errors.New("router.Context: file path is required") ErrSessionManagerNotSet = errors.New("router.Context: session manager is not configured") ErrDownloadFilenameInvalid = errors.New("router.Context: download filename is invalid") )
var ErrCSRFEncryptionKey = errors.New("router: CSRFOptions.EncryptionKey must be exactly 32 bytes (AES-256) when EnableXSRFCookie is set")
ErrCSRFEncryptionKey is returned by NewCSRFMiddleware when EnableXSRFCookie is true but EncryptionKey is not exactly csrfEncryptionKeySize bytes. See ADR-006.
Functions ¶
func Bind ¶
Bind decodes the request body as JSON into v, then validates it using struct validate tags. Returns a *DomainError if decoding or validation fails. Bodies are capped at 1 MiB (413 beyond it); use BindMax to raise the cap for endpoints that legitimately accept larger payloads.
WARNING — unlike BindForm, Bind applies no mass-assignment guard: a client can set any json-exposed field, including server-owned ones such as model.BaseModel's id/created_at/updated_at. encoding/json offers no per-field skip-on-decode without also hiding the field from responses, so the guard cannot be applied transparently here. Bind JSON onto a dedicated input type that omits server-owned fields, or zero those fields after decoding, when the target embeds a persistence model.
func BindForm ¶
BindForm decodes an application/x-www-form-urlencoded or multipart/form-data request into v, then validates it using struct validate tags — the form counterpart of Bind.
Field resolution order: a `form:"name"` tag wins, then `json:"name"`, then the case-insensitive field name (first match wins if two form keys differ only by case); `form:"-"` skips a field. Supported field kinds: string, bool, signed and unsigned integers, floats, time.Time (RFC 3339, the datetime-local format 2006-01-02T15:04 — parsed as UTC since the wire format carries no offset — or 2006-01-02) and pointers to those. Embedded value structs are flattened; pointer embeddings are not traversed. Form keys without a matching field are ignored; present-but-empty values leave the field at its zero value so optional numeric inputs submit cleanly. Checkbox values "on" bind as true. Bodies are capped at 10 MiB.
Mass-assignment protection: fields tagged `db:"pk"` or `db:"readonly"` are server-owned (model.BaseModel's ID/CreatedAt/UpdatedAt) and are never bound from request input — a client-submitted `id` or `created_at` is ignored, leaving whatever the caller pre-set (zero on a create, the loaded value on an update). This is skip, not clear: binding onto a loaded record preserves its identity. NOTE the asymmetry — Bind (JSON) does NOT yet apply this guard (encoding/json offers no per-field skip without also hiding the field from responses); callers binding JSON onto persistence models must still zero server-owned fields themselves or bind through an input type.
Returns a *DomainError if parsing, conversion, or validation fails.
func BindMax ¶
BindMax is Bind with a caller-chosen body cap in bytes. maxBytes <= 0 falls back to the default 1 MiB cap — an accidental zero must never mean "unlimited".
func CORSMiddleware ¶
func CORSMiddleware(opts CORSOptions) func(http.Handler) http.Handler
CORSMiddleware returns middleware that handles Cross-Origin Resource Sharing. It processes preflight OPTIONS requests and sets the appropriate CORS headers on all responses.
func CSRFMiddleware ¶
func CSRFMiddleware(opts CSRFOptions) func(http.Handler) http.Handler
CSRFMiddleware returns middleware that protects against cross-site request forgery. It implements a two-layer approach (Laravel-style): 1. Origin verification via Sec-Fetch-Site header (if enabled) 2. Traditional CSRF token validation as fallback
Features: - Origin verification for modern browsers - Session-based or cookie-based token storage - Encrypted X-XSRF-TOKEN cookie for JavaScript frameworks - Token rotation for enhanced security - Configurable origin-only mode and same-site allowance
CSRFMiddleware panics on a misconfiguration (the regexp.MustCompile pattern) — a bad CSRF config is a deployment error that should crash the process at startup, not serve requests with a weak key. The panic fires once, at middleware-chain construction, never on the request path. Use NewCSRFMiddleware for a non-panicking, error-returning alternative. See ADR-006.
func CSRFToken ¶
CSRFToken returns the CSRF token for the current request, for templates to embed in forms. When the CSRF middleware is in the chain it returns the exact token that middleware resolved (injected into the context) — authoritative across cookie/session storage and any configured session key. Absent the middleware it falls back to the default cookie/session lookup.
func Compress ¶
Compress returns middleware that gzip-compresses response bodies for clients that accept gzip encoding. level follows compress/flate constants.
func ContextHandler ¶
func ContextHandler(handlers ...Handler) http.HandlerFunc
ContextHandler adapts a Handler to http.HandlerFunc.
func Created ¶
func Created(w http.ResponseWriter, data interface{})
Created writes a 201 Created response with the given JSON data.
func DefaultStack ¶
DefaultStack returns the standard middleware chain for Nucleus applications.
func Error ¶
Error writes an error as a structured JSON response. If the error is a *DomainError, its status code and details are used; otherwise a generic 500 is returned.
func IsWebSocketUpgrade ¶
func JSON ¶
func JSON(w http.ResponseWriter, status int, data interface{})
JSON writes a JSON response with the given status code and data.
func Matched ¶
Matched reports whether a registered route serves the request, as the caller holds it. The dispatching Mux resolves the route against the request's method and path each time Matched is called, so a middleware mounted with Use can let an unregistered path fall through to the mux's own 404 instead of answering for a handler that does not exist — the framework's default-deny authorizer and the CSRF middleware both do, through WhenMatched. The decision follows the request as each middleware sees it: a middleware that rewrites the path changes the answer for everything after it.
The decision sees through mounted sub-routers (Route, or Mount with a *Mux): at the parent, a path under a mount prefix counts as matched only when the sub-router — or a sub-router of its own, any depth down — has a route for the rest of the path, so a gate mounted at the root judges the same route table a gate inside the mount would. A handler mounted with Mount that is not a Mux is opaque, and everything under its prefix reports true. A method-only mismatch (the path is registered for other methods) reports false, and the mux answers 405.
When no Mux has dispatched the request — the middleware is wrapped around a plain http.Handler, or the test calls it directly — there is no routing decision to consult and Matched reports true, so every security layer keeps enforcing as if the route existed.
func NewCSRFMiddleware ¶
NewCSRFMiddleware builds the CSRF protection middleware, returning an error on a misconfiguration instead of panicking. Use this constructor when the caller wants to surface configuration errors through its own validation path; use CSRFMiddleware for the panic-on-misconfiguration (regexp.MustCompile-style) variant.
The error case today is EnableXSRFCookie set without a 32-byte EncryptionKey — see ADR-006.
func Paginate ¶
Paginate extracts page and page_size from query parameters with defaults and bounds. page defaults to 1, page_size to defaultSize (max 100).
func RateLimitFromPolicy ¶
func RateLimitFromPolicy(policy RateLimitPolicy) func(http.Handler) http.Handler
RateLimitFromPolicy builds the request limiter DefaultStack would mount for policy, with the default key (tenant and user from the context, else client IP) and the default route and role dimensions. It exists so an application can mount the limiter AFTER its identity middleware: the key reads the user id, the claims and the tenant from the request context, and a limiter mounted before the bearer is decoded only ever sees an IP. A policy with Requests <= 0 yields a pass-through.
func RateLimitMiddleware ¶
func RateLimitMiddleware(opts RateLimitOptions) func(http.Handler) http.Handler
RateLimitMiddleware enforces a token-bucket request limit: capacity is Requests+Burst tokens, refilled continuously at Requests per Window. This is smoother than a fixed window (no boundary bursts of 2× the limit) — the historical "fixed-window" description here was wrong; the implementation has always been the token bucket below.
func RealIP ¶
RealIP rewrites r.RemoteAddr with the client IP taken from X-Forwarded-For / X-Real-IP — but ONLY when the immediate peer is a trusted proxy. On its own (the exported middleware) no proxies are trusted, so forwarding headers are ignored and r.RemoteAddr is left untouched. Use the router's WithTrustedProxies option (wired from the `trusted_proxies` config key) to honor forwarding headers behind a known load balancer. Trusting these headers unconditionally lets any client spoof its IP — evading per-IP rate limits and poisoning audit logs (H-N3).
func Recoverer ¶
Recoverer catches panics in downstream handlers, logs the stack trace, and returns a 500 Internal Server Error response. It logs through the process default logger; DefaultStack uses RecovererWithLogger so the panic goes through the application's handler (redaction, attributes, sink) like every other line.
func RecovererWithLogger ¶
RecovererWithLogger is Recoverer logging through logger; nil falls back to slog.Default().
func RequestID ¶
RequestID generates a unique request identifier and stores it in the request context. The ID is also written as the X-Request-Id response header.
func RequestLogger ¶
RequestLogger returns middleware that logs each HTTP request with slog. It records method, path, status, duration, request_id, remote_addr, and user_agent.
func RouteFromContext ¶
RouteFromContext returns the route template ("/users/{id}") the mux matched for this request, or "" when nothing has matched yet — inside a handler it is always set. It is what the telemetry reports as http.route.
func SecurityHeaders ¶
SecurityHeaders sets standard security headers on every response. HSTS is emitted when the request arrives over a direct TLS connection. Behind a TLS-terminating proxy (r.TLS == nil) use the router's WithHSTS option / an `env: production` app so the header is still sent.
func TelemetryMiddleware ¶
TelemetryMiddleware records OpenTelemetry spans and metrics for HTTP requests.
func TimeoutMiddleware ¶
TimeoutMiddleware wraps the stdlib http.TimeoutHandler to cancel requests that exceed the given duration. It automatically skips WebSocket upgrades and requests that accept text/event-stream.
func TimeoutMiddlewareWithExemptions ¶
func TimeoutMiddlewareWithExemptions(timeout time.Duration, exemptPrefixes []string) func(http.Handler) http.Handler
TimeoutMiddlewareWithExemptions is TimeoutMiddleware with URL path prefixes that bypass it. http.TimeoutHandler buffers the response and hides http.Flusher, so a streaming handler behind it cannot flush a byte until it returns; an exempt subtree gets the raw writer and no deadline. A timeout <= 0 disables the middleware for every route.
Types ¶
type CORSOptions ¶
type CORSOptions struct {
AllowedOrigins []string
AllowedMethods []string
AllowedHeaders []string
ExposedHeaders []string
AllowCredentials bool
MaxAge int // seconds
}
CORSOptions configures the CORS middleware.
type CSRFOptions ¶
type CSRFOptions struct {
// ExemptPaths are URL path prefixes that skip CSRF validation (e.g. "/api/").
ExemptPaths []string
// CookieName is the name of the CSRF cookie (default: "_csrf").
// The cookie-prefix names "__Host-…" / "__Secure-…" are supported and
// recommended over HTTPS: the middleware always issues the cookie with
// Path=/ and no Domain, so the only prefix precondition it enforces is
// that InsecureCookie stays false (the prefixes require Secure) —
// NewCSRFMiddleware/CSRFMiddleware reject the combination.
CookieName string
// HeaderName is the HTTP header checked for the token (default: "X-CSRF-Token").
HeaderName string
// FormField is the form field name checked for the token (default: "_csrf_token").
FormField string
// InsecureCookie disables the Secure flag on CSRF / XSRF cookies.
// The zero value (false) is the production-safe path: cookies are
// issued with Secure=true and refuse to ride over plain HTTP. Set
// this to true only for local-dev plain-HTTP runs. See ADR-008.
InsecureCookie bool
// Origin verification options (Laravel-style two-layer approach)
EnableOriginCheck bool // Enable Sec-Fetch-Site header verification (zero value: false; router.WithCSRF sets it true)
OriginOnly bool // Use only origin verification, disable token fallback (zero value: false)
AllowSameSite bool // Allow same-site requests in addition to same-origin (zero value: false)
// Session-based token storage (more secure than cookie)
UseSessionToken bool // Store token in session instead of cookie (default: false)
SessionKey string // Session key for token storage (default: "csrf_token")
// X-XSRF-TOKEN encrypted cookie for JavaScript frameworks
EnableXSRFCookie bool // Enable encrypted XSRF-TOKEN cookie for JS frameworks (default: false)
XSRFCookieName string // XSRF-TOKEN cookie name (default: "XSRF-TOKEN")
EncryptionKey []byte // AES-256 key for encrypting XSRF-TOKEN (exactly 32 bytes; see ADR-006 and ADR-008).
// Token rotation
RotateToken bool // Regenerate token after each successful validation (default: false)
// Logger receives WARN-level entries when the server-side encryption
// of the XSRF-TOKEN cookie fails, and DEBUG-level entries when the
// incoming X-XSRF-TOKEN header fails to decrypt (browser noise from
// stale or tampered tokens). When nil, slog.Default() is used. See
// ADR-008.
Logger *slog.Logger
}
CSRFOptions configures the CSRF protection middleware.
type Context ¶
type Context struct {
Writer http.ResponseWriter
Request *http.Request
// contains filtered or unexported fields
}
Context is a unified request context for handlers. It wraps http.ResponseWriter and *http.Request and adds helpers for: - URL/query/form access - sessions - template binding/rendering - typed responses (JSON/XML/file/download)
func NewContext ¶
func NewContext(w http.ResponseWriter, r *http.Request, handlers []Handler, opts ...ContextOption) *Context
NewContext creates a Context from an HTTP request/response pair.
func (*Context) HTML ¶
HTML renders a named template using merged bound data and call data. Values from data override previously bound keys.
func (*Context) SessionDestroy ¶
SessionDestroy destroys the current session.
func (*Context) SessionGetBool ¶
SessionGetBool reads a bool value from session.
func (*Context) SessionGetInt ¶
SessionGetInt reads an int value from session.
func (*Context) SessionGetString ¶
SessionGetString reads a string value from session.
func (*Context) SessionManager ¶
func (c *Context) SessionManager() *auth.SessionManager
SessionManager returns the injected session manager.
func (*Context) SessionPutBool ¶
SessionPutBool writes a bool value to session.
func (*Context) SessionPutInt ¶
SessionPutInt writes an int value to session.
func (*Context) SessionPutString ¶
SessionPutString writes a string value to session.
func (*Context) SessionRemove ¶
SessionRemove removes one key from session.
func (*Context) SessionRenewToken ¶
SessionRenewToken renews the current session token.
func (*Context) T ¶
T translates a message key for the request's negotiated locale. It reads the translator and locale the i18n middleware stored on the request context (the framework mounts that middleware when compiled catalogs are found under `locales_path`; see pkg/i18n). Without the middleware it degrades to the key itself, fmt-formatted when args are given — the behaviour of an untranslated application, never an error.
type ContextHandlerFunc ¶
type ContextHandlerFunc = Handler
ContextHandlerFunc is an alias for Handler to maintain backward compatibility.
type ContextOption ¶
type ContextOption func(*Context)
ContextOption configures a Context.
func WithSession ¶
func WithSession(sm *auth.SessionManager) ContextOption
WithSession injects an auth session manager into Context.
func WithTemplates ¶
func WithTemplates(t *template.Template) ContextOption
WithTemplates injects a template engine into Context.
type HTTPError ¶
HTTPError represents an error with an associated HTTP status code.
func NewHTTPError ¶
NewHTTPError creates a new HTTPError.
type Handler ¶
Handler is a function that processes a request and returns an error.
func FromHTTP ¶
func FromHTTP(h http.HandlerFunc) Handler
FromHTTP adapts a standard http.HandlerFunc to a router.Handler.
func FromHandler ¶
FromHandler adapts a standard http.Handler to a router.Handler.
type Middleware ¶
Middleware is a function that wraps an http.Handler with additional behavior.
func WhenMatched ¶
func WhenMatched(gate Middleware) Middleware
WhenMatched wraps a gate so it only judges requests a registered route serves. Where the gate sits, an unmatched request passes through untouched and the mux's 404 (or 405) answers; a matched one goes through the gate as usual. A gate that stepped aside is not forgotten: if a middleware mounted after it rewrites the path onto a registered route, the gate runs anyway — ahead of the next WhenMatched gate that sees the rewritten request, or at dispatch when none follows — in its mounted order and on the path as the gate's own level spells it, so a rewrite cannot turn a miss into an unguarded hit. A gate mounted at the root judges the full path even when the rewrite happened inside a mounted sub-router: policy rows and CSRF exemptions are written against the full path, and the stripped path lives in another namespace (a rewrite of /legacy onto /secret inside Route("/api") is judged as /api/secret, never as /secret). The handler still receives the stripped request, with the context the gates passed down. Outside a Mux there is no routing decision and the gate always runs.
The framework's default-deny authorizer and the CSRF middleware are built with it; a custom gate mounted with Use can be too.
type Mux ¶
type Mux struct {
// contains filtered or unexported fields
}
Mux wraps http.ServeMux with convenience methods for route registration, middleware chaining, grouping, and sub-router mounting. It serves as a drop-in replacement for chi.Router using only the Go standard library (requires Go 1.22+ for method-aware patterns and path value extraction).
func (*Mux) Group ¶
Group creates an inline scope that shares the parent's ServeMux but maintains its own middleware stack. Middlewares added via Use inside the group only apply to routes registered within that group.
func (*Mux) HandleFunc ¶
func (m *Mux) HandleFunc(pattern string, h http.HandlerFunc)
HandleFunc registers a HandlerFunc for all HTTP methods matching pattern.
func (*Mux) Mount ¶
Mount registers handler under the given pattern prefix. Requests matching the prefix are forwarded to handler with the prefix stripped. If pattern does not end with "/", a trailing slash is appended so that the ServeMux treats it as a subtree pattern.
func (*Mux) Resource ¶
func (m *Mux) Resource(pattern string, handlers ResourceHandlers)
Resource registers a conventional REST route set for one resource prefix: - GET /<resource>/ -> List - POST /<resource>/ -> Create - GET /<resource>/{id} -> Retrieve - PUT /<resource>/{id} -> Update - DELETE /<resource>/{id} -> Delete
Example:
r.Resource("/users", router.ResourceHandlers{ ... })
func (*Mux) Route ¶
Route creates a sub-router mounted under the given pattern prefix. The sub- router has its own middleware stack and its own route namespace, and inherits the parent's session manager and template engine (QCD-FW-8).
func (*Mux) ServeHTTP ¶
func (m *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP dispatches the request through the middleware chain and into the underlying ServeMux.
func (*Mux) SetHTMLTemplates ¶
SetHTMLTemplates sets the template engine for the Mux and its sub-routers.
func (*Mux) SetSessionManager ¶
func (m *Mux) SetSessionManager(sm *auth.SessionManager)
SetSessionManager sets the session manager for the Mux and its sub-routers.
func (*Mux) Static ¶
Static registers a handler to serve static files from root directory under the given pattern prefix.
func (*Mux) Use ¶
func (m *Mux) Use(mws ...Middleware)
Use appends one or more middlewares to the Mux's middleware stack. For top-level Mux instances, middlewares are applied via ServeHTTP to all requests. For Group scopes, middlewares wrap individual handlers at registration time.
func (*Mux) Walk ¶
func (m *Mux) Walk(fn func(method string, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error) error
Walk iterates over all registered routes, calling fn for each one. The signature is compatible with the chi.Walk callback API so that callers can migrate without code changes beyond the call site.
func (*Mux) With ¶
func (m *Mux) With(mws ...Middleware) *Mux
With adds a list of middlewares to an inline sub-router and returns it.
type Option ¶
type Option func(*routerOpts)
Option configures a Router during creation.
func WithCORSCredentials ¶
WithCORSCredentials controls whether the CORS middleware emits Access-Control-Allow-Credentials: true. It defaults to false (SEC-1, security-by-default): credentialed cross-origin responses are only emitted when the app explicitly opts in with WithCORSCredentials(true). Because the Fetch standard forbids combining credentials with the `*` wildcard — and reflecting every Origin with credentials is itself unsafe — credentials must be paired with an explicit origin allow-list (WithCORSOrigins). Enabling credentials without an allow-list is a misconfiguration.
func WithCORSOrigins ¶
WithCORSOrigins sets allowed CORS origins. An empty list allows all origins.
func WithCSRFInsecureCookie ¶
WithCSRFInsecureCookie disables the Secure attribute on the CSRF cookies. Development-only opt-out, mirroring the session cookie posture: with the default (Secure) cookie, the double-submit flow is unreachable for plain HTTP clients such as Go's cookiejar over http://127.0.0.1 — browsers special-case localhost as trustworthy, non-browser clients do not.
func WithDevelopmentErrors ¶
WithDevelopmentErrors controls what a handler error that is neither a DomainError nor an HTTPError puts on the wire. Off — the default — the response is a 500 with a generic body and the error itself goes to the log, with the request id so the two can be joined; a driver's message or a file path belongs in the log, not in a browser. On, meant for `env: development`, the body carries err.Error() so a developer sees the cause without opening the log. app.New sets it from the environment.
func WithHSTS ¶
WithHSTS makes the security-headers middleware emit Strict-Transport-Security on every response, not only over a direct TLS connection. Enable it in production (typically behind a TLS-terminating proxy, where r.TLS is nil): app.New wires it from `env: production`. Leave it off in development so plain-HTTP local runs are not pinned to HTTPS.
func WithRateLimit ¶
WithRateLimit enables in-process request rate limiting. Requests <= 0 disables the limiter.
func WithRateLimitPolicy ¶
func WithRateLimitPolicy(policy RateLimitPolicy) Option
WithRateLimitPolicy enables in-process request rate limiting with optional burst, route-level, and role-level dimensions.
func WithTimeout ¶
WithTimeout sets the request timeout in seconds. Zero or negative disables the timeout middleware entirely; prefer WithTimeoutExempt to carve out the handful of routes that stream (SSE, long polls, large downloads) and keep the timeout on everything else.
func WithTimeoutExempt ¶
WithTimeoutExempt excludes URL path prefixes from the request timeout. http.TimeoutHandler buffers the whole response and hides http.Flusher, so a streaming handler behind it can never flush: exempt its subtree and the handler gets the raw writer, with Flush and Hijack, and no deadline. Requests whose Accept header asks for text/event-stream are exempt without listing them.
func WithTrustedProxies ¶
WithTrustedProxies sets the allow-list of upstream proxy addresses (IPs or CIDR ranges) whose X-Forwarded-For / X-Real-IP headers the RealIP middleware is allowed to honor. With no trusted proxies (the default) forwarding headers are ignored and r.RemoteAddr — the immediate peer — is the client IP, which prevents header-spoofed rate-limit evasion and audit poisoning.
type RateLimitOptions ¶
type RateLimitOptions struct {
Requests int
Window time.Duration
Burst int
ScopeByRoute bool
ScopeByRole bool
KeyFunc func(*http.Request) string
RouteDimension func(*http.Request) string
RoleDimension func(*http.Request) string
}
RateLimitOptions configures rate limiting middleware.
type RateLimitPolicy ¶
type RateLimitPolicy struct {
Requests int
Window time.Duration
Burst int
ByRoute bool
ByRole bool
}
RateLimitPolicy describes advanced limiter dimensions.
type ResourceHandlers ¶
type ResourceHandlers struct {
List Handler
Create Handler
Retrieve Handler
Update Handler
Delete Handler
}
ResourceHandlers groups CRUD handlers for one REST resource. Nil handlers are skipped.
type RouteEntry ¶
type RouteEntry struct {
Method string
Pattern string
Middlewares int
// contains filtered or unexported fields
}
RouteEntry represents a registered route for introspection via Walk.
type Router ¶
type Router struct {
*Mux
// contains filtered or unexported fields
}
Router wraps a Mux with Nucleus conventions and a default middleware stack.
type WrapResponseWriter ¶
type WrapResponseWriter struct {
http.ResponseWriter
// contains filtered or unexported fields
}
WrapResponseWriter is a response writer wrapper that captures the HTTP status code and the number of bytes written. It replaces chi/middleware's equivalent.
func NewWrapResponseWriter ¶
func NewWrapResponseWriter(w http.ResponseWriter, _ int) *WrapResponseWriter
NewWrapResponseWriter creates a new WrapResponseWriter. The protoMajor argument is accepted for API compatibility but currently unused.
func (*WrapResponseWriter) BytesWritten ¶
func (w *WrapResponseWriter) BytesWritten() int
BytesWritten returns the total bytes written to the response body.
func (*WrapResponseWriter) Flush ¶
func (w *WrapResponseWriter) Flush()
Flush implements http.Flusher if the underlying writer supports it.
func (*WrapResponseWriter) Hijack ¶
func (w *WrapResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error)
Hijack implements http.Hijacker if the underlying writer supports it.
func (*WrapResponseWriter) Status ¶
func (w *WrapResponseWriter) Status() int
Status returns the HTTP status code that was written.
func (*WrapResponseWriter) Unwrap ¶
func (w *WrapResponseWriter) Unwrap() http.ResponseWriter
Unwrap returns the underlying ResponseWriter for middleware compatibility.
func (*WrapResponseWriter) WriteHeader ¶
func (w *WrapResponseWriter) WriteHeader(code int)
func (*WrapResponseWriter) WroteHeader ¶
func (w *WrapResponseWriter) WroteHeader() bool
WroteHeader reports whether the status line has been written (via an explicit WriteHeader or an implicit first Write). Recoverer consults it to avoid a second WriteHeader after a mid-response panic.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package interceptor is the contract a third-party request interceptor implements — and nothing else.
|
Package interceptor is the contract a third-party request interceptor implements — and nothing else. |