41 lines
1.1 KiB
TypeScript
41 lines
1.1 KiB
TypeScript
import { Request, Response, NextFunction } from 'express';
|
|
|
|
// Simple in-memory rate limiter
|
|
const requestCounts = new Map<string, { count: number; resetTime: number }>();
|
|
|
|
export function rateLimiter(maxRequests: number = 10, windowMs: number = 60000) {
|
|
return (req: Request, res: Response, next: NextFunction): void => {
|
|
const ip = req.ip || req.socket.remoteAddress || req.headers['x-forwarded-for']?.toString() || 'unknown';
|
|
const now = Date.now();
|
|
const record = requestCounts.get(ip);
|
|
|
|
if (!record || now > record.resetTime) {
|
|
requestCounts.set(ip, { count: 1, resetTime: now + windowMs });
|
|
next();
|
|
return;
|
|
}
|
|
|
|
if (record.count >= maxRequests) {
|
|
res.status(429).json({
|
|
error: true,
|
|
code: 'RATE_LIMITED',
|
|
message: '请求过于频繁,请稍后再试',
|
|
});
|
|
return;
|
|
}
|
|
|
|
record.count++;
|
|
next();
|
|
};
|
|
}
|
|
|
|
// Cleanup stale entries periodically
|
|
setInterval(() => {
|
|
const now = Date.now();
|
|
for (const [key, value] of requestCounts.entries()) {
|
|
if (now > value.resetTime) {
|
|
requestCounts.delete(key);
|
|
}
|
|
}
|
|
}, 60000);
|