Engineering Craft › Design Patterns
Middleware
A pipeline of functions wrapped around request handling.
Also known as: middleware, request pipeline, Express middleware
Middleware is a pipeline of functions wrapped around request handling. Each function receives the request, can do something before or after the real handler, and then passes control to the next one.
// Express
app.use((req, res, next) => { // runs for every request
console.log(req.method, req.url);
next(); // hand over to the next step
});
app.use(requireLogin); // may stop the chain with a 401
app.get("/orders", listOrders); // the actual handler
request ─► logging ─► auth ─► parse body ─► handler ─► response
└──────────── each step can act before and after ────────┘
What it’s used for
Cross-cutting concerns that apply to many routes, so they don’t need to be repeated in each handler:
- Logging and request IDs.
- Authentication and authorization.
- Parsing JSON bodies and cookies.
- CORS headers and compression.
- Rate limiting.
- Error handling and response formatting.
How it works
Each middleware is a function that either:
- calls
next()to continue down the chain, - or ends the request itself (sending a 401, or a cached response).
Order matters. Auth must run before handlers that need it, and error handlers usually go last.
# Python (ASGI-style, simplified)
async def timing(request, call_next):
start = time.time()
response = await call_next(request)
response.headers["X-Time"] = str(time.time() - start)
return response
Cautions
- Forgetting
next()leaves the request hanging. - Order bugs: a body parser placed after the route never sees the body.
- Too much work in middleware slows every request.
- Hidden behavior: when something odd happens to a request, check the middleware stack (request lifecycle).
The idea is related to the decorator and chain of responsibility patterns.