mw
HTTP middleware - compose lists of fn(req, res, next) handlers, built-in middleware for logging, panic recovery (500), security headers, body size limits, timeouts, IP allow/block lists, HTTP Basic Auth, Bearer token auth, API key auth, in-memory sliding-window rate limiting, request ID injection, health check endpoint, response time header, content-type negotiation, HTTPS redirect, and a per-route circuit breaker.
Load with: use mw
What this module does
mw implements the standard HTTP middleware pattern. Each piece
of middleware is a function fn(req, res, next) - it may inspect
or mutate the request, call next(req, res) to continue the
chain, or short-circuit by writing a response directly. mw.chain
and mw.compose combine middleware lists into a single handler.
Quick example
use mw
use srv
# Build a middleware stack
handler = mw.chain([
mw.log(),
mw.recover(),
mw.security(),
mw.request_id(),
mw.rate_limit(100, 60, \(req) srv.reqip(req)),
mw.bearer(\(tok) verify_jwt(tok))
], \(req, res) srv.resjn(res, {ok: tru}))
# Register with server
srv.srvrt(app, "GET", "/api/data", handler)
Middleware
Composition
mwcha(mws, final) / mw.chain(mws, final)Chains a list of middleware and a final handler into one fn(req, res).
mwcom(mws) / mw.compose(mws)Combines a list of middleware into one fn(req, res, next) that can itself be used as middleware.
Logging and resilience
mwlog() / mw.log()Logs METHOD path Nms via obs after each request.
mwrec() / mw.recover()Wraps the chain in try. On error, sends a 500 and logs the error.
mwrt() / mw.response_time()Adds an X-Response-Time: Nms header.
mwrid() / mw.request_id()Generates a unique request ID, sets it on req.request_id and the X-Request-ID response header.
Security
mwsec() / mw.security()Adds X-Content-Type-Options, X-Frame-Options, X-XSS-Protection, Strict-Transport-Security, and Referrer-Policy headers.
mwlim(max) / mw.limit(max)Rejects requests whose body exceeds max bytes with a 400.
mwtmo(ms) / mw.timeout(ms)Sends a 504 if the handler hasn't completed within ms milliseconds.
mwip(whitelist, blacklist) / mw.ip(wl, bl)Blocks requests from IPs in blacklist or not in whitelist (either may be nil).
mwhtt() / mw.https()Redirects HTTP requests to HTTPS with a 301.
Authentication
mwbas(creds) / mw.basic_auth(creds)HTTP Basic Auth. creds is an object mapping username → password. Sets req.user on success.
mwbea(vfn) / mw.bearer(vfn)Bearer token auth. Calls vfn(token); if truthy, sets req.user to the result.
mwkey(header, vfn) / mw.api_key(header, vfn)API key auth from a named header. Sets req.api_key and req.api_user on success.
Rate limiting and circuit breaking
mwrat(max, window_s, keyfn) / mw.rate_limit(max, win, keyfn)In-memory sliding-window rate limiter. keyfn(req) returns the key (e.g. client IP). Sends 429 when exceeded.
mwcir(name, threshold, timeout_ms) / mw.circuit_breaker(name, thresh, tmo)Per-name circuit breaker. Opens after threshold failures and returns 503 until timeout_ms elapses.
Utilities
mwhea(path, cb) / mw.health(path, cb)Intercepts requests to path and calls cb(). Returns 200 {status:"healthy"} or 503 {status:"unhealthy"}.
mwneg(default) / mw.negotiate(default)Content negotiation. Sets req.accepts to "json", "html", "text", or the default based on the Accept header.
Notes
- Requires
trl,txt,srv,tim,obs,enc, anddet.