/** * Rate Limiting Middleware * Prevents abuse by limiting requests per IP/user */ import { RateLimitError } from './errorHandler.mjs' // In-memory store for rate limiting (use Redis in production) const requestCounts = new Map() // Clean up old entries every minute setInterval(() => { const now = Date.now() for (const [key, data] of requestCounts.entries()) { if (now - data.windowStart > data.windowMs) { requestCounts.delete(key) } } }, 60000) /** * Create rate limiter middleware * @param {Object} options - Rate limit options * @param {number} options.windowMs - Time window in milliseconds * @param {number} options.max - Max requests per window * @param {string} options.message - Error message * @param {Function} options.keyGenerator - Function to generate unique key */ export function rateLimit(options = {}) { const { windowMs = 60000, // 1 minute max = 100, message = 'Zu viele Anfragen. Bitte versuche es später erneut.', keyGenerator = (req) => req.ip, } = options return (req, res, next) => { const key = keyGenerator(req) const now = Date.now() let data = requestCounts.get(key) if (!data || now - data.windowStart > windowMs) { data = { count: 0, windowStart: now, windowMs } requestCounts.set(key, data) } data.count++ // Set rate limit headers res.set({ 'X-RateLimit-Limit': max, 'X-RateLimit-Remaining': Math.max(0, max - data.count), 'X-RateLimit-Reset': new Date(data.windowStart + windowMs).toISOString(), }) if (data.count > max) { return next(new RateLimitError(message)) } next() } } /** * Pre-configured rate limiters */ export const limiters = { // General API rate limit api: rateLimit({ windowMs: 60000, max: 100, message: 'API Rate Limit überschritten', }), // Stricter limit for auth endpoints auth: rateLimit({ windowMs: 900000, // 15 minutes max: 10, message: 'Zu viele Anmeldeversuche. Bitte warte 15 Minuten.', }), // Limit for email sorting (expensive operation) emailSort: rateLimit({ windowMs: 60000, max: 30, // Erhöht für Entwicklung message: 'E-Mail-Sortierung ist limitiert. Bitte warte eine Minute.', }), // Limit for AI operations ai: rateLimit({ windowMs: 60000, max: 20, message: 'KI-Anfragen sind limitiert.', }), }