M

Middleware

Create reusable middleware functions with proper TypeScript types.

Code

typescript
1import { Request, Response, NextFunction } from "express";
2
3// Extend Request type for custom properties
4interface AuthenticatedRequest extends Request {
5 user?: {
6 id: number;
7 email: string;
8 roles: string[];
9 };
10}
11
12// Logging middleware
13function logger(
14 req: Request,
15 res: Response,
16 next: NextFunction
17): void {
18 const start = Date.now();
19
20 res.on("finish", () => {
21 const duration = Date.now() - start;
22 console.log(`${req.method} ${req.path} ${res.statusCode} - ${duration}ms`);
23 });
24
25 next();
26}
27
28// Authentication middleware
29function authenticate(
30 req: AuthenticatedRequest,
31 res: Response,
32 next: NextFunction
33): void {
34 const token = req.headers.authorization?.replace("Bearer ", "");
35
36 if (!token) {
37 res.status(401).json({ error: "No token provided" });
38 return;
39 }
40
41 // Simulated token validation
42 if (token === "valid-token") {
43 req.user = {
44 id: 1,
45 email: "user@example.com",
46 roles: ["user", "admin"],
47 };
48 next();
49 } else {
50 res.status(401).json({ error: "Invalid token" });
51 }
52}
53
54// Role-based authorization middleware factory
55function requireRole(...roles: string[]) {
56 return (
57 req: AuthenticatedRequest,
58 res: Response,
59 next: NextFunction
60 ): void => {
61 if (!req.user) {
62 res.status(401).json({ error: "Not authenticated" });
63 return;
64 }
65
66 const hasRole = roles.some((role) => req.user!.roles.includes(role));
67
68 if (!hasRole) {
69 res.status(403).json({ error: "Insufficient permissions" });
70 return;
71 }
72
73 next();
74 };
75}
76
77// Rate limiting middleware
78function rateLimit(maxRequests: number, windowMs: number) {
79 const requests = new Map<string, { count: number; resetTime: number }>();
80
81 return (req: Request, res: Response, next: NextFunction): void => {
82 const ip = req.ip || "unknown";
83 const now = Date.now();
84 const record = requests.get(ip);
85
86 if (!record || now > record.resetTime) {
87 requests.set(ip, { count: 1, resetTime: now + windowMs });
88 next();
89 return;
90 }
91
92 if (record.count >= maxRequests) {
93 res.status(429).json({ error: "Too many requests" });
94 return;
95 }
96
97 record.count++;
98 next();
99 };
100}
101
102// Usage example
103// app.use(logger);
104// app.use("/api", authenticate);
105// app.use("/admin", requireRole("admin"));
106// app.use(rateLimit(100, 60000)); // 100 requests per minute
107
108export { logger, authenticate, requireRole, rateLimit, AuthenticatedRequest };

Run this example locally

$ npx ts-node backend/middleware.ts