Express middleware functions are the building blocks of Express applications. They're functions that execute during the request-response cycle and have access to the request object (req), response object (res), and the next middleware function (next).
Middleware functions can perform various tasks: execute code, modify request/response objects, end the request-response cycle, or call the next middleware in the stack. They're perfect for cross-cutting concerns like logging, authentication, error handling, and request parsing.
The key to understanding middleware is the execution flow. When a request comes in, Express runs middleware functions in the order they're registered using app.use() or route-specific methods. Each middleware must either end the response (by sending data back) or call next() to pass control to the next middleware.
For logging middleware, you typically want to:
next() immediately so the request continues processingThe response object emits events during its lifecycle. The 'finish' event is particularly useful because it fires when the response has been sent to the client, making it perfect for measuring total request time.
Middleware functions are often created by factory functions - functions that return the actual middleware. This pattern allows you to configure the middleware with options while keeping the middleware signature standard.
1import express, { Request, Response, NextFunction } from 'express';
2
3function simpleMiddleware() {
4 return (req: Request, res: Response, next: NextFunction) => {
5 console.log('Request received at:', new Date().toISOString());
6
7 res.on('finish', () => {
8 console.log('Response sent');
9 });
10
11 next(); // Continue to next middleware
12 };
13}
14
15const app = express();
16app.use(simpleMiddleware());
17
18app.get('/', (req, res) => {
19 res.send('Hello World');
20});