33 lines
848 B
TypeScript
33 lines
848 B
TypeScript
const WINDOW_MS = 6000;
|
|
const MAX_REQUESTS = 60;
|
|
|
|
const hits = new Map<string, { count: number; resetAt: number }>();
|
|
|
|
export default defineEventHandler((event) => {
|
|
const path = getRequestURL(event).pathname;
|
|
if (!path.startsWith("/api/")) return;
|
|
|
|
const ip = getRequestIP(event, { xForwardedFor: true }) ?? "127.0.0.1";
|
|
const now = Date.now();
|
|
|
|
let entry = hits.get(ip);
|
|
if (!entry || now >= entry.resetAt) {
|
|
entry = { count: 0, resetAt: now + WINDOW_MS };
|
|
hits.set(ip, entry);
|
|
}
|
|
|
|
entry.count++;
|
|
|
|
setHeader(event, "X-RateLimit-Limit", MAX_REQUESTS);
|
|
setHeader(
|
|
event,
|
|
"X-RateLimit-Remaining",
|
|
Math.max(0, MAX_REQUESTS - entry.count),
|
|
);
|
|
|
|
if (entry.count > MAX_REQUESTS) {
|
|
setHeader(event, "Retry-After", "1");
|
|
throw createError({ statusCode: 429, statusMessage: "Too Many Requests" });
|
|
}
|
|
});
|