Documentation
¶
Overview ¶
Package middleware provides Vukem's built-in net/http middleware. Every constructor returns a func(http.Handler) http.Handler, so they compose with any other middleware. Errors are rendered through web.Fail, which uses the router's error handler (problem+json, HTML or htmx fragments).
Index ¶
- Constants
- func CSPNonce(ctx context.Context) string
- func WriteMaintenance(file string, m MaintenanceState) error
- type CORSConfig
- type MaintenanceConfig
- type MaintenanceState
- type Middleware
- func BodyLimit(n int64) Middleware
- func CORS(cfg CORSConfig) (Middleware, error)
- func Gzip() Middleware
- func JSONOnly() Middleware
- func Logger(log *slog.Logger) Middleware
- func Maintenance(cfg MaintenanceConfig) Middleware
- func MethodOverride() Middleware
- func Recover() Middleware
- func RequestID() Middleware
- func SecureHeaders(cfg SecureHeadersConfig) Middleware
- func Static(root *os.Root, cfg StaticConfig) Middleware
- func StaticFS(fsys fs.FS, cfg StaticConfig) Middleware
- func Timeout(d time.Duration) Middleware
- type SecureHeadersConfig
- type StaticConfig
Constants ¶
const DefaultCSP = "default-src 'self'; script-src 'self' 'nonce-{nonce}'; style-src 'self' 'nonce-{nonce}'; " +
"img-src 'self' data:; font-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'self'; " +
"frame-ancestors 'none'; form-action 'self'"
DefaultCSP is a strict policy suitable for server-rendered pages with nonce'd scripts and styles.
const DefaultMaintenanceFile = "storage/framework/down"
DefaultMaintenanceFile is where `vukem down` writes the maintenance state.
const MaintenanceCookie = "vukem_maintenance"
MaintenanceCookie carries the bypass granted by visiting /<secret>.
const RequestIDHeader = "X-Request-ID"
RequestIDHeader is the header carrying the request id.
Variables ¶
This section is empty.
Functions ¶
func CSPNonce ¶
CSPNonce returns the per-request CSP nonce, or "" when SecureHeaders did not run. Templates expose it as {{ cspNonce }}.
func WriteMaintenance ¶ added in v0.18.0
func WriteMaintenance(file string, m MaintenanceState) error
WriteMaintenance puts the app in maintenance mode (vukem down).
Types ¶
type CORSConfig ¶
type CORSConfig struct {
// AllowedOrigins lists exact origins ("https://app.example.com") or "*".
AllowedOrigins []string
// AllowedMethods defaults to GET, HEAD, POST, PUT, PATCH, DELETE.
AllowedMethods []string
// AllowedHeaders defaults to Accept, Authorization, Content-Type,
// X-Requested-With, X-CSRF-Token.
AllowedHeaders []string
// ExposedHeaders are readable by the browser.
ExposedHeaders []string
// AllowCredentials allows cookies/Authorization; incompatible with "*".
AllowCredentials bool
// MaxAge caches preflight responses.
MaxAge time.Duration
}
CORSConfig configures cross-origin resource sharing. The zero value allows no cross-origin requests (deny by default).
type MaintenanceConfig ¶ added in v0.18.0
type MaintenanceConfig struct {
// File is the state file (default DefaultMaintenanceFile).
File string
// Key signs bypass cookies (derive it from APP_KEY).
Key []byte
// Except lists paths always served (default "/up").
Except []string
// Secure marks the bypass cookie Secure (production, HTTPS).
Secure bool
}
MaintenanceConfig configures Maintenance.
type MaintenanceState ¶ added in v0.18.0
type MaintenanceState struct {
// Secret, when set, lets visitors of /<secret> through (stored hashed).
Secret string `json:"-"`
// Retry is sent as Retry-After.
Retry time.Duration `json:"-"`
SecretHash string `json:"secret_hash,omitempty"`
RetryAfter int `json:"retry_after,omitempty"`
Since time.Time `json:"since"`
}
MaintenanceState is the state written by `vukem down`.
type Middleware ¶
Middleware wraps an http.Handler.
func BodyLimit ¶
func BodyLimit(n int64) Middleware
BodyLimit caps request bodies at n bytes; larger bodies fail with 413.
func CORS ¶
func CORS(cfg CORSConfig) (Middleware, error)
CORS returns CORS middleware. Register it as server middleware so preflight requests are answered before routing. It returns an error for insecure configurations ("*" with credentials), so misconfiguration fails at boot (A02).
func Gzip ¶
func Gzip() Middleware
Gzip compresses text-like responses for clients that accept gzip. Bodies smaller than 1 KiB, already-encoded responses, ranges and event streams are passed through.
func JSONOnly ¶
func JSONOnly() Middleware
JSONOnly makes a route group JSON-only: write requests must send JSON (415 otherwise) and errors render as problem+json.
func Logger ¶
func Logger(log *slog.Logger) Middleware
Logger logs one structured line per request (method, path, status, duration, size, request id). 5xx log at ERROR, 4xx at WARN.
func Maintenance ¶ added in v0.18.0
func Maintenance(cfg MaintenanceConfig) Middleware
Maintenance answers 503 (Retry-After, the "errors/503" view or problem+json) while the state file exists. Visiting /<secret> sets a signed bypass cookie. A file that cannot be read keeps the app down.
func MethodOverride ¶
func MethodOverride() Middleware
MethodOverride lets HTML forms send PUT, PATCH and DELETE through a hidden "_method" field on POST. Multipart forms put it in the action's query string instead ("?_method=PUT"), so their body is never buffered. Register it as server middleware so routing sees the overridden method.
func Recover ¶
func Recover() Middleware
Recover converts panics into 500 responses rendered by the error handler and logs the stack trace server-side only (A10). http.ErrAbortHandler is re-raised so net/http can abort the connection.
func RequestID ¶
func RequestID() Middleware
RequestID reuses a well-formed incoming X-Request-ID or generates one, stores it in the context (web.RequestID) and echoes it in the response.
func SecureHeaders ¶
func SecureHeaders(cfg SecureHeadersConfig) Middleware
SecureHeaders sets security headers on every response (A02).
func Static ¶
func Static(root *os.Root, cfg StaticConfig) Middleware
Static serves files from root when they exist and passes other requests on. Files are opened through os.Root, so ".." and symlinks cannot escape the directory (A01); dotfiles and directory listings are never served. The caller owns root and closes it on shutdown.
func StaticFS ¶
func StaticFS(fsys fs.FS, cfg StaticConfig) Middleware
StaticFS is Static over any fs.FS (e.g. an embed.FS in production).
func Timeout ¶
func Timeout(d time.Duration) Middleware
Timeout sets a deadline on the request context. Handlers and queries that respect the context stop when it expires.
type SecureHeadersConfig ¶
type SecureHeadersConfig struct {
// CSP is the Content-Security-Policy; "{nonce}" is replaced with a
// per-request nonce. Empty uses DefaultCSP; "-" disables the header.
CSP string
// HSTSMaxAge enables Strict-Transport-Security on HTTPS requests.
// Zero uses two years; negative disables it.
HSTSMaxAge time.Duration
// FrameOptions defaults to DENY; "-" disables it.
FrameOptions string
// ReferrerPolicy defaults to strict-origin-when-cross-origin.
ReferrerPolicy string
// PermissionsPolicy defaults to camera=(), microphone=(), geolocation=().
PermissionsPolicy string
// TrustForwardedProto treats X-Forwarded-Proto: https as HTTPS (set it
// only behind a trusted proxy).
TrustForwardedProto bool
// DevServer returns the origin of a running asset dev server (the Vite
// hot URL) or "". When set, the origin is allowed in script-src,
// style-src, img-src, font-src and connect-src (plus its ws:// form for
// hot reload). Wire it only outside production.
DevServer func() string
}
SecureHeadersConfig configures SecureHeaders. Zero values use the secure defaults documented in docs/security.md.
type StaticConfig ¶
type StaticConfig struct {
// Prefix is the URL prefix ("/" serves files at the root).
Prefix string
// ImmutablePrefixes get a one-year immutable cache (hashed build output).
ImmutablePrefixes []string
}
StaticConfig configures Static.