Express Middleware Chain: Logging and Authentication

mediumTypeScript

Lesson

Express Middleware: The Foundation of Request Processing

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.

How Middleware Works

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.

Common Middleware Patterns

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.

Example
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});
L6Middleware functions receive req, res, and next parameters
L8Call next() to continue to the next middleware in the chain
L23app.use() applies middleware to all routes that follow

Key Takeaways

  • •Middleware functions run in sequence and must call next() to continue the request chain
  • •Use app.use() to apply middleware to all routes, or attach it to specific routes for targeted functionality
  • •Middleware enables separation of concerns by handling cross-cutting logic like auth and logging outside route handlers
Loading...