Middleware in Express is one of the most powerful concepts for building web applications. Think of middleware as a chain of functions that every request passes through before reaching your route handlers. Each middleware function can inspect, modify, or respond to requests, and then decide whether to continue to the next middleware or stop the chain.
Every middleware function receives three parameters: req (the request object), res (the response object), and next (a function to call the next middleware). The next() function is crucial—it's how you tell Express "I'm done with this request, pass it to the next middleware or route handler."
Middleware executes in the order you define it. If you have logging middleware followed by authentication middleware, every request will be logged first, then authenticated. This sequential nature makes middleware predictable and powerful for implementing cross-cutting concerns like logging, authentication, error handling, and request validation.
Authentication middleware typically checks headers or cookies, validates credentials, and either allows the request to continue or responds with an error. Logging middleware captures request information for debugging or analytics. Error handling middleware catches exceptions and formats error responses consistently.
The beauty of middleware is reusability. Write authentication logic once, apply it to any route that needs protection. Create logging middleware that works across your entire application. This separation of concerns keeps your route handlers focused on business logic while middleware handles infrastructure concerns.
1import express, { Request, Response, NextFunction } from 'express';
2
3const app = express();
4
5// Simple logging middleware
6function simpleLogger(req: Request, res: Response, next: NextFunction) {
7 console.log(`${req.method} ${req.path}`);
8 next(); // Continue to next middleware
9}
10
11// Timing middleware
12function responseTime(req: Request, res: Response, next: NextFunction) {
13 const start = Date.now();
14
15 res.on('finish', () => {
16 const duration = Date.now() - start;
17 console.log(`Request took ${duration}ms`);
18 });
19
20 next();
21}
22
23// Apply middleware to all routes
24app.use(simpleLogger);
25app.use(responseTime);
26
27app.get('/api/data', (req, res) => {
28 res.json({ message: 'Hello World' });
29});