| import { Request, Response, NextFunction } from 'express'; |
| import rateLimit from 'express-rate-limit'; |
|
|
| export const requestLogger = (req: Request, res: Response, next: NextFunction) => { |
| const start = Date.now(); |
| res.on('finish', () => { |
| const duration = Date.now() - start; |
| console.log(`${req.method} ${req.path} ${res.statusCode} - ${duration}ms - ${req.ip}`); |
| }); |
| next(); |
| }; |
|
|
| export const sanitizeRequestBody = (req: Request, res: Response, next: NextFunction) => { |
| if (req.body && typeof req.body === 'object') { |
| const sanitize = (obj: any): any => { |
| if (Array.isArray(obj)) { |
| return obj.map(sanitize); |
| } |
| if (obj && typeof obj === 'object') { |
| const sanitized: any = {}; |
| for (const key in obj) { |
| if (typeof obj[key] === 'string') { |
| |
| sanitized[key] = obj[key].replace(/<script[^>]*>.*?<\/script>/gi, ''); |
| } else { |
| sanitized[key] = sanitize(obj[key]); |
| } |
| } |
| return sanitized; |
| } |
| return obj; |
| }; |
| req.body = sanitize(req.body); |
| } |
| next(); |
| }; |
|
|
| export const validateRequestSize = (maxSize: number = 10485760) => { |
| return (req: Request, res: Response, next: NextFunction) => { |
| const contentLength = parseInt(req.headers['content-length'] || '0', 10); |
| if (contentLength > maxSize) { |
| return res.status(413).json({ error: 'Request entity too large' }); |
| } |
| next(); |
| }; |
| }; |
|
|
| export const createStrictRateLimiter = (windowMs: number, max: number) => { |
| return rateLimit({ |
| windowMs, |
| max, |
| message: 'Too many requests from this IP, please try again later.', |
| standardHeaders: true, |
| legacyHeaders: false, |
| |
| }); |
| }; |
|
|
| export const createAuthRateLimiter = () => { |
| return rateLimit({ |
| windowMs: 15 * 60 * 1000, |
| max: 5, |
| message: 'Too many authentication attempts. Please try again later.', |
| skipSuccessfulRequests: true, |
| standardHeaders: true, |
| legacyHeaders: false, |
| }); |
| }; |
|
|
| export const createPasswordResetRateLimiter = () => { |
| return rateLimit({ |
| windowMs: 60 * 60 * 1000, |
| max: 3, |
| message: 'Too many password reset requests. Please try again later.', |
| standardHeaders: true, |
| legacyHeaders: false, |
| }); |
| }; |
|
|
|
|