import { Request, Response, NextFunction } from "express"; interface ThrottleConfig { windowMs: number; maxRequests: number; } const throttleConfigs: Map = new Map(); const requestCounts: Map = new Map(); /** * API throttling middleware */ export function apiThrottle(config: ThrottleConfig) { return (req: Request, res: Response, next: NextFunction) => { const key = req.headers["x-api-key"] as string || req.ip || "unknown"; const now = Date.now(); let record = requestCounts.get(key); if (!record || now > record.resetAt) { record = { count: 0, resetAt: now + config.windowMs, }; requestCounts.set(key, record); } record.count++; // Set rate limit headers res.setHeader("X-RateLimit-Limit", config.maxRequests.toString()); res.setHeader("X-RateLimit-Remaining", Math.max(0, config.maxRequests - record.count).toString()); res.setHeader("X-RateLimit-Reset", new Date(record.resetAt).toISOString()); if (record.count > config.maxRequests) { return res.status(429).json({ error: "Rate limit exceeded", message: `Maximum ${config.maxRequests} requests per ${config.windowMs}ms`, retryAfter: Math.ceil((record.resetAt - now) / 1000), }); } next(); }; } /** * Set throttle configuration for a route */ export function setThrottleConfig(path: string, config: ThrottleConfig) { throttleConfigs.set(path, config); }