Built-in and Custom Middleware
Express comes with several built-in middleware functions and supports an enormous ecosystem of third-party middleware. You can also write your own middleware for logging, authentication, validation, and more.
Middleware functions receive three arguments: req, res, and next. They can modify the request or response objects, end the cycle by sending a response, or call next() to pass control to the next middleware.
const express = require('express');
const app = express();
// --- Built-in Middleware ---
app.use(express.json()); // Parse JSON bodies
app.use(express.urlencoded({ extended: true })); // Parse form data
app.use(express.static('public')); // Serve static files
// --- Custom Middleware: Request Logger ---
function logger(req, res, next) {
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
console.log(`${req.method} ${req.url} ${res.statusCode} - ${duration}ms`);
});
next();
}
app.use(logger);
// --- Custom Middleware: Auth Check ---
function requireAuth(req, res, next) {
const token = req.headers.authorization;
if (!token) {
return res.status(401).json({ error: 'No token provided' });
}
// Verify token here...
next();
}
// Apply to specific routes only
app.get('/api/profile', requireAuth, (req, res) => {
res.json({ user: 'Alice' });
}); - express.json() — Parse incoming JSON request bodies
- express.urlencoded() — Parse URL-encoded form data
- express.static() — Serve static files from a directory
- app.use(fn) — Apply middleware to all routes
- app.get('/path', middleware, handler) — Apply middleware to specific routes
- Middleware executes in the order it is defined. Place global middleware (like logger, body parser) before your routes.
Error Handling Middleware
Error handling middleware is special — it takes four arguments (err, req, res, next). Express recognizes it by the four parameters. When an error is thrown or passed to next(err), Express skips to the error handler.
Always define error handling middleware last, after all routes. This catches errors from any route or middleware above it.
const express = require('express');
const app = express();
app.use(express.json());
// Route that might throw an error
app.get('/api/users/:id', (req, res, next) => {
try {
const id = parseInt(req.params.id);
if (isNaN(id)) {
const error = new Error('Invalid user ID');
error.statusCode = 400;
throw error;
}
res.json({ id, name: 'Alice' });
} catch (err) {
next(err); // Pass error to error handler
}
});
// 404 handler — must be after all routes
app.use((req, res, next) => {
res.status(404).json({ error: 'Route not found' });
});
// Error handling middleware (4 arguments!)
app.use((err, req, res, next) => {
console.error('Error:', err.message);
const status = err.statusCode || 500;
res.status(status).json({
error: err.message || 'Internal Server Error'
});
});
app.listen(3000); - Error middleware MUST have exactly 4 parameters (err, req, res, next) — even if you do not use next. Express uses the parameter count to identify it as an error handler.
Third-Party Middleware
The Express ecosystem has hundreds of useful middleware packages. Common ones include morgan for logging, cors for cross-origin requests, and helmet for security headers.
Install them with npm and use them like any other middleware.
// npm install morgan cors helmet
const express = require('express');
const morgan = require('morgan'); // HTTP request logger
const cors = require('cors'); // Cross-Origin Resource Sharing
const helmet = require('helmet'); // Security headers
const app = express();
// Apply third-party middleware
app.use(helmet()); // Set security headers
app.use(cors()); // Allow cross-origin requests
app.use(morgan('dev')); // Log requests: GET /api/users 200 5ms
app.use(express.json());
// CORS with options
app.use(cors({
origin: 'http://localhost:3000',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
credentials: true
}));
app.get('/api/data', (req, res) => {
res.json({ message: 'Secured and logged!' });
});
app.listen(3000); - helmet() sets various HTTP headers to protect your app from common web vulnerabilities like XSS, clickjacking, and MIME sniffing.
