UNPKG

express-rate-limiter-ts

Version:

A powerful, flexible and modern rate limiter middleware for Express.js written in TypeScript.

123 lines (122 loc) 5.21 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.RedisStore = void 0; const ioredis_1 = __importDefault(require("ioredis")); // RedisStore: Production için tam çalışan, asenkron, TTL ve ban destekli bir store. class RedisStore { constructor(options) { this.statsKey = 'rateLimiter:stats'; this.banPrefix = 'rateLimiter:ban:'; this.countPrefix = 'rateLimiter:count:'; this.windowMs = options.windowMs; this.client = new ioredis_1.default(options.url); } // Sayaç artırma ve limiti kontrol etme (asenkron) incr(key) { return __awaiter(this, void 0, void 0, function* () { const redisKey = this.countPrefix + key; // Sayaç artırılır, anahtar yoksa TTL atanır const current = yield this.client.incr(redisKey); if (current === 1) { yield this.client.pexpire(redisKey, this.windowMs); } const ttl = yield this.client.pttl(redisKey); return { current, remaining: 0, // Kalan limit middleware'de hesaplanacak resetTime: new Date(Date.now() + (ttl > 0 ? ttl : this.windowMs)), exceeded: false, }; }); } // Sayaç okuma (asenkron) get(key) { return __awaiter(this, void 0, void 0, function* () { const redisKey = this.countPrefix + key; const count = parseInt((yield this.client.get(redisKey)) || '0', 10); const ttl = yield this.client.pttl(redisKey); return { count, resetTime: Date.now() + (ttl > 0 ? ttl : this.windowMs) }; }); } // Sayaç sıfırlama reset(key) { return __awaiter(this, void 0, void 0, function* () { yield this.client.del(this.countPrefix + key); }); } // İstatistik kaydı (isteğe bağlı) recordStat(route) { return __awaiter(this, void 0, void 0, function* () { yield this.client.hincrby(this.statsKey, route, 1); yield this.client.hset(this.statsKey + ':last', route, Date.now()); }); } // İstatistikleri döndür getStats() { return __awaiter(this, void 0, void 0, function* () { const counts = yield this.client.hgetall(this.statsKey); const lasts = yield this.client.hgetall(this.statsKey + ':last'); const stats = {}; for (const route in counts) { stats[route] = { count: parseInt(counts[route], 10), lastTriggered: new Date(Number(lasts[route]) || Date.now()), }; } return stats; }); } // Ban uygula ban(key, seconds, reason) { return __awaiter(this, void 0, void 0, function* () { yield this.client.set(this.banPrefix + key, reason, 'EX', seconds); }); } // Ban kontrolü isBanned(key) { return __awaiter(this, void 0, void 0, function* () { const reason = yield this.client.get(this.banPrefix + key); if (reason) { const ttl = yield this.client.ttl(this.banPrefix + key); return { banned: true, banExpiresAt: new Date(Date.now() + ttl * 1000), reason }; } return { banned: false }; }); } // Banlı anahtarları döndür (tümünü tarar, büyük veri için optimize edilmeli) getBanned() { return __awaiter(this, void 0, void 0, function* () { const keys = yield this.client.keys(this.banPrefix + '*'); const result = {}; for (const fullKey of keys) { const key = fullKey.replace(this.banPrefix, ''); const reason = yield this.client.get(fullKey); const ttl = yield this.client.ttl(fullKey); if (reason && ttl > 0) { result[key] = { banExpiresAt: new Date(Date.now() + ttl * 1000), reason }; } } return result; }); } // Ban kaldır unban(key) { return __awaiter(this, void 0, void 0, function* () { yield this.client.del(this.banPrefix + key); yield this.client.del(this.countPrefix + key); }); } } exports.RedisStore = RedisStore;