An ordered pipeline
In Express, middleware form a chain (a pipeline). The request goes through them in the order they are registered, and each link decides:
- call
next()to yield control to the next one, or - respond (
res.json,res.status…) and not callnext(), which stops the chain right there.
app.use(logger); // 1st for ALL routes
app.use(requireAuth); // 2nd
app.get("/tasks", listTasks); // final handler
If requireAuth responds with a 401, the handler listTasks never runs:
the request is already resolved.
Global vs. per-route
- Global (
app.use(fn)): applies to all requests. Useful for logging, body parsing, common headers. - Per-route (
app.get("/admin", requireAuth, handler)): applies only to that route. Useful when the check doesn't make sense everywhere.
Application-level middleware (logging)
A classic case is logging every request. The middleware usually enriches
the req object (adds data to it) or notes something somewhere before passing the baton:
function logger(req, res, next) {
req.timestamp = Date.now(); // enriches the request
console.log(req.method, req.url);
next(); // essential so the request doesn't hang!
}
Golden rule: a middleware that doesn't respond must call
next(). If it forgets, the request stays hung forever.