Express Middleware Explained
Understand Express middleware - functions that process requests. Learn to create and use middleware effectively.
Express Middleware Explained
Middleware = functions that run between request and response. They're Express's superpower.
What is Middleware?
```javascript function middleware(req, res, next) { // Do something with request console.log('Request received'); // Pass to next middleware next(); } ```
The Request Flow
``` Request → Middleware 1 → Middleware 2 → Route Handler → Response ```
Using Middleware
```javascript const express = require('express'); const app = express();
// Apply to ALL routes app.use((req, res, next) => { console.log(`${req.method} ${req.url}`); next(); });
// Apply to specific path app.use('/api', (req, res, next) => { console.log('API request'); next(); });
// Routes app.get('/', (req, res) => res.send('Home')); ```
Built-in Middleware
```javascript // Parse JSON bodies app.use(express.json());
// Parse URL-encoded bodies (form data) app.use(express.urlencoded({ extended: true }));
// Serve static files app.use(express.static('public')); ```
Creating Custom Middleware
**Logger:** ```javascript function logger(req, res, next) { const timestamp = new Date().toISOString(); console.log(`[${timestamp}] ${req.method} ${req.url}`); next(); }
app.use(logger); ```
**Request Timer:** ```javascript function timer(req, res, next) { req.startTime = Date.now(); res.on('finish', () => { const duration = Date.now() - req.startTime; console.log(`Request took ${duration}ms`); }); next(); }
app.use(timer); ```
**Auth Check:** ```javascript function requireAuth(req, res, next) { const token = req.headers.authorization; if (!token) { return res.status(401).json({ error: 'No token provided' }); } // Verify token... req.user = { id: 1, name: 'Alice' }; next(); }
// Use on specific routes app.get('/api/profile', requireAuth, (req, res) => { res.json(req.user); }); ```
Order Matters!
```javascript // ✅ Correct - body parser before routes app.use(express.json()); app.post('/data', (req, res) => { console.log(req.body); // Works! });
// ❌ Wrong - body parser after route app.post('/data', (req, res) => { console.log(req.body); // undefined! }); app.use(express.json()); ```
Error Handling Middleware
```javascript // Regular middleware has 3 params // Error middleware has 4 (err first) app.use((err, req, res, next) => { console.error(err.stack); res.status(500).json({ error: 'Something broke!' }); });
// Trigger error app.get('/error', (req, res, next) => { next(new Error('Oops!')); }); ```
Third-Party Middleware
```javascript const cors = require('cors'); const helmet = require('helmet'); const morgan = require('morgan');
app.use(cors()); // Enable CORS app.use(helmet()); // Security headers app.use(morgan('dev')); // Request logging ```
Middleware Factory
```javascript function rateLimit(maxRequests, windowMs) { const requests = new Map(); return (req, res, next) => { const ip = req.ip; const now = Date.now(); if (!requests.has(ip)) { requests.set(ip, []); } const userRequests = requests.get(ip) .filter(time => now - time < windowMs); if (userRequests.length >= maxRequests) { return res.status(429).json({ error: 'Too many requests' }); } userRequests.push(now); requests.set(ip, userRequests); next(); }; }
// 100 requests per minute app.use(rateLimit(100, 60000)); ```
Key Takeaway
Middleware processes requests in order. Always call `next()` to continue the chain. Use built-in middleware for JSON/forms, third-party for logging/security, and custom for app-specific logic. Put them before your routes!