UNPKG

express-rate-limiter-ts

Version:

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

136 lines (135 loc) 5.63 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()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MongoStore = void 0; const mongodb_1 = require("mongodb"); // MongoStore: Production için tam çalışan, asenkron, TTL ve ban destekli bir store. class MongoStore { constructor(options) { this.windowMs = options.windowMs; this.client = new mongodb_1.MongoClient(options.uri); } // Bağlantıyı başlat (ilk kullanımda çağrılmalı) connect() { return __awaiter(this, void 0, void 0, function* () { if (!this.db) { yield this.client.connect(); this.db = this.client.db(); this.counters = this.db.collection('rateLimiter_counters'); this.bans = this.db.collection('rateLimiter_bans'); this.stats = this.db.collection('rateLimiter_stats'); // TTL index'leri oluştur (bir kereye mahsus) yield this.counters.createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 }); yield this.bans.createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 }); } }); } // Sayaç artırma ve limiti kontrol etme incr(key) { return __awaiter(this, void 0, void 0, function* () { var _a, _b; yield this.connect(); const now = new Date(); const expiresAt = new Date(now.getTime() + this.windowMs); const result = yield this.counters.findOneAndUpdate({ key }, { $inc: { count: 1 }, $setOnInsert: { createdAt: now }, $set: { expiresAt }, }, { upsert: true, returnDocument: 'after' }); return { current: (_b = (_a = result === null || result === void 0 ? void 0 : result.value) === null || _a === void 0 ? void 0 : _a.count) !== null && _b !== void 0 ? _b : 1, remaining: 0, // Kalan limit middleware'de hesaplanacak resetTime: expiresAt, exceeded: false, }; }); } // Sayaç okuma get(key) { return __awaiter(this, void 0, void 0, function* () { yield this.connect(); const doc = yield this.counters.findOne({ key }); if (!doc) return { count: 0, resetTime: Date.now() + this.windowMs }; return { count: doc.count, resetTime: doc.expiresAt.getTime() }; }); } // Sayaç sıfırlama reset(key) { return __awaiter(this, void 0, void 0, function* () { yield this.connect(); yield this.counters.deleteOne({ key }); }); } // İstatistik kaydı recordStat(route) { return __awaiter(this, void 0, void 0, function* () { yield this.connect(); yield this.stats.updateOne({ route }, { $inc: { count: 1 }, $set: { lastTriggered: new Date() } }, { upsert: true }); }); } // İstatistikleri döndür getStats() { return __awaiter(this, void 0, void 0, function* () { yield this.connect(); const docs = yield this.stats.find().toArray(); const stats = {}; for (const doc of docs) { stats[doc.route] = { count: doc.count, lastTriggered: doc.lastTriggered, }; } return stats; }); } // Ban uygula ban(key, seconds, reason) { return __awaiter(this, void 0, void 0, function* () { yield this.connect(); const expiresAt = new Date(Date.now() + seconds * 1000); yield this.bans.updateOne({ key }, { $set: { reason, expiresAt } }, { upsert: true }); }); } // Ban kontrolü isBanned(key) { return __awaiter(this, void 0, void 0, function* () { yield this.connect(); const doc = yield this.bans.findOne({ key }); if (doc && doc.expiresAt > new Date()) { return { banned: true, banExpiresAt: doc.expiresAt, reason: doc.reason }; } return { banned: false }; }); } // Banlı anahtarları döndür getBanned() { return __awaiter(this, void 0, void 0, function* () { yield this.connect(); const now = new Date(); const docs = yield this.bans.find({ expiresAt: { $gt: now } }).toArray(); const result = {}; for (const doc of docs) { result[doc.key] = { banExpiresAt: doc.expiresAt, reason: doc.reason }; } return result; }); } // Ban kaldır unban(key) { return __awaiter(this, void 0, void 0, function* () { yield this.connect(); yield this.bans.deleteOne({ key }); yield this.counters.deleteOne({ key }); }); } } exports.MongoStore = MongoStore;