Chapter 8: Advanced Express Patterns
Chapter 8 of 15
Chapter 8: Advanced Express Patterns
8.1 Middleware Patterns
Middleware functions have access to request, response, and next. They can execute code, modify request/response, and call the next middleware.
// Custom middleware
function logger(req, res, next) {
console.log(`${req.method} ${req.path} - ${new Date()}`);
next();
}
function authenticate(req, res, next) {
const token = req.headers.authorization;
if (!token) {
return res.status(401).json({ error: 'Unauthorized' });
}
// Verify token
req.user = decodeToken(token);
next();
}
// Error handling middleware
function errorHandler(err, req, res, next) {
console.error(err.stack);
res.status(500).json({ error: 'Something went wrong!' });
}
app.use(logger);
app.use('/api', authenticate);
app.use(errorHandler);
8.2 Route Middleware
// Route-specific middleware
app.get('/profile', authenticate, (req, res) => {
res.json({ user: req.user });
});
// Multiple middleware
app.post('/posts', authenticate, validatePost, createPost);
// Middleware array
const middleware = [authenticate, validateInput, rateLimit];
app.put('/users/:id', middleware, updateUser);
8.3 Async Middleware
// Wrapper for async middleware
const asyncHandler = (fn) => (req, res, next) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
// Usage
app.get('/users/:id', asyncHandler(async (req, res) => {
const user = await User.findById(req.params.id);
res.json(user);
}));
8.4 Router Organization
// routes/users.js
const express = require('express');
const router = express.Router();
router.get('/', getUsers);
router.get('/:id', getUser);
router.post('/', createUser);
router.put('/:id', updateUser);
router.delete('/:id', deleteUser);
module.exports = router;
// app.js
const userRoutes = require('./routes/users');
app.use('/api/users', userRoutes);