UNPKG

@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
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