Keyborg/server/src/middleware/rateLimiter.ts

53 lines
1.6 KiB
TypeScript

import { Middleware } from "@lib/router.ts";
import log from "@shared/utils/logger.ts";
const requestCounts: Partial<
Record<string, { count: number; lastReset: number }>
> = {};
const MAX_REQUESTS_PER_WINDOW = 300;
const RATE_LIMIT_WINDOW = 60000;
const rateLimitMiddleware: Middleware = async (c, next) => {
const hostnameOpt = c.hostname;
if (hostnameOpt.isSome()) {
const hostname = hostnameOpt.value;
const clientCount = requestCounts[hostname];
const now = Date.now();
if (!clientCount || now - clientCount.lastReset > RATE_LIMIT_WINDOW) {
requestCounts[hostname] = { count: 1, lastReset: now };
} else if (clientCount.count < MAX_REQUESTS_PER_WINDOW) {
clientCount.count++;
} else if (c.preferredType.isSome()) {
log.info(`client ${hostname} is rate limeted`);
switch (c.preferredType.value) {
case "html": {
return c.html("429 Too Many Requests", {
status: 429,
});
}
case "json": {
return c.json(
{
err: "429 Too Many Requests",
},
{
status: 429,
},
);
}
}
} else {
return new Response("429 Too Many Request", {
status: 429,
});
}
}
await next();
};
export default rateLimitMiddleware;