@pulzar/core
Version:
Next-generation Node.js framework for ultra-fast web applications with zero-reflection DI, GraphQL, WebSockets, events, and edge runtime support
86 lines • 3.1 kB
JavaScript
export class RateLimiter {
options;
requests = new Map();
constructor(options) {
this.options = options;
}
getKey(req) {
if (this.options.keyGenerator) {
return this.options.keyGenerator(req);
}
return req.ip || "unknown";
}
isRateLimited(key) {
const now = Date.now();
const record = this.requests.get(key);
if (!record) {
this.requests.set(key, {
count: 1,
resetTime: now + this.options.windowMs,
});
return false;
}
if (now > record.resetTime) {
this.requests.set(key, {
count: 1,
resetTime: now + this.options.windowMs,
});
return false;
}
if (record.count >= this.options.max) {
return true;
}
record.count++;
return false;
}
middleware() {
return async (request, reply) => {
const key = this.getKey(request);
if (this.isRateLimited(key)) {
const message = this.options.message || "Too many requests";
const statusCode = this.options.statusCode || 429;
if (this.options.headers) {
const record = this.requests.get(key);
if (record) {
reply.header("X-RateLimit-Limit", this.options.max.toString());
reply.header("X-RateLimit-Remaining", "0");
reply.header("X-RateLimit-Reset", new Date(record.resetTime).toISOString());
}
}
return reply.code(statusCode).send({ error: message });
}
// Add headers if requested
if (this.options.headers) {
const record = this.requests.get(key);
if (record) {
reply.header("X-RateLimit-Limit", this.options.max.toString());
reply.header("X-RateLimit-Remaining", (this.options.max - record.count).toString());
reply.header("X-RateLimit-Reset", new Date(record.resetTime).toISOString());
}
}
};
}
}
export function createRateLimitMiddleware(options = {}) {
const defaultOptions = {
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: "Too many requests from this IP",
statusCode: 429,
headers: true,
skipSuccessfulRequests: false,
skipFailedRequests: false,
};
const rateLimitOptions = {
...defaultOptions,
...options,
};
const limiter = new RateLimiter(rateLimitOptions);
return limiter.middleware();
}
export function registerRateLimitPlugin(fastify, options = {}) {
const rateLimitHook = createRateLimitMiddleware(options);
fastify.addHook("preHandler", rateLimitHook);
}
export const rateLimitMiddleware = createRateLimitMiddleware({});
//# sourceMappingURL=rate.interceptor.js.map