Loading lessons...
Writing Custom Middleware Functions
Creating Reusable Middleware
Custom middleware allows modularizing logic such as authentication checks, request validation, rate limiting, and request transformation.
Example 1: API Key Authentication Middleware
function requireApiKey(req, res, next) {
const apiKey = req.headers["x-api-key"];
if (!apiKey || apiKey !== "secret-token-123") {
return res.status(401).json({ error: "Unauthorized: Invalid or missing API Key" });
}
// API Key valid -> attach context and call next()
req.apiClient = { role: "admin" };
next();
}
// Mounting middleware on specific routes
app.get("/api/protected-data", requireApiKey, (req, res) => {
res.json({ data: "Top secret content", client: req.apiClient });
});
Example 2: Configurable Middleware Factory Function
// Factory function returning custom middleware
function restrictToRoles(...allowedRoles) {
return (req, res, next) => {
if (!req.user || !allowedRoles.includes(req.user.role)) {
return res.status(403).json({ error: "Forbidden: Insufficient privileges" });
}
next();
};
}
// Usage in routes
app.delete("/api/users/:id", requireApiKey, restrictToRoles("admin", "superadmin"), (req, res) => {
res.json({ message: "User deleted" });
});
TL;DR
- Custom middleware can inspect headers, modify
reqobjects, or return early responses. - Use higher-order factory functions to pass configurable parameters into middleware.