UNPKG

express-rate-limiter-ts

Version:

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

120 lines (119 loc) 6.02 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 }); const express_1 = __importDefault(require("express")); const supertest_1 = __importDefault(require("supertest")); const rateLimiter_1 = require("../src/rateLimiter"); const memoryStore_1 = require("../src/storage/memoryStore"); const dummyStore_1 = require("../src/storage/dummyStore"); describe('RateLimiter Otomasyon Testleri', () => { let app; let store; beforeEach(() => { app = (0, express_1.default)(); store = new memoryStore_1.MemoryStore(1000); app.use((0, rateLimiter_1.rateLimiter)({ windowMs: 1000, max: 2, message: 'Limit aşıldı', whitelist: ['127.0.0.1'], blacklist: (req) => req.header('x-api-key') === 'banned-key', customResponse: (req, res, info) => { if (info.banned) { res.status(429).json({ error: 'Banlandınız', banExpiresAt: info.banExpiresAt }); } else if (info.exceeded) { res.status(429).json({ error: 'Limit aşıldı', kalan: 0 }); } }, banSeconds: 2, // 2 saniye ban dynamicMax: (req) => req.header('x-api-key') === 'premium' ? 5 : 2, identifierType: 'header', identifierHeader: 'x-api-key', }, store)); app.get('/api', (_req, res) => res.send('ok')); }); it('Normal kullanıcı 2 istekte limitlenir', () => __awaiter(void 0, void 0, void 0, function* () { yield (0, supertest_1.default)(app).get('/api').expect(200); yield (0, supertest_1.default)(app).get('/api').expect(200); yield (0, supertest_1.default)(app).get('/api').expect(429); })); it('Whitelist kullanıcı hiç limitlenmez', () => __awaiter(void 0, void 0, void 0, function* () { app.set('trust proxy', true); for (let i = 0; i < 10; i++) { yield (0, supertest_1.default)(app).get('/api').set('X-Forwarded-For', '127.0.0.1').expect(200); } })); it('Blacklist kullanıcı anında engellenir', () => __awaiter(void 0, void 0, void 0, function* () { yield (0, supertest_1.default)(app).get('/api').set('x-api-key', 'banned-key').expect(403); })); it('Premium kullanıcı daha fazla istek atabilir', () => __awaiter(void 0, void 0, void 0, function* () { for (let i = 0; i < 5; i++) { yield (0, supertest_1.default)(app).get('/api').set('x-api-key', 'premium').expect(200); } yield (0, supertest_1.default)(app).get('/api').set('x-api-key', 'premium').expect(429); })); it('Ban süresi dolunca tekrar erişim sağlanır', () => __awaiter(void 0, void 0, void 0, function* () { yield (0, supertest_1.default)(app).get('/api').expect(200); yield (0, supertest_1.default)(app).get('/api').expect(200); yield (0, supertest_1.default)(app).get('/api').expect(429); // Ban süresi kadar bekle yield new Promise((r) => setTimeout(r, 2100)); yield (0, supertest_1.default)(app).get('/api').expect(200); })); }); describe('Header ve Yapılandırma Testleri', () => { let app; let store; beforeEach(() => { app = (0, express_1.default)(); store = new memoryStore_1.MemoryStore(1000); app.use((0, rateLimiter_1.rateLimiter)({ windowMs: 1000, max: 2, identifierType: 'header', identifierHeader: 'x-api-key', }, store)); app.get('/api', (_req, res) => res.send('ok')); }); it('X-RateLimit-* ve RateLimit-* headerları doğru set edilir', () => __awaiter(void 0, void 0, void 0, function* () { const res = yield (0, supertest_1.default)(app).get('/api').set('x-api-key', 'test'); expect(res.headers['x-ratelimit-limit']).toBeDefined(); expect(res.headers['x-ratelimit-remaining']).toBeDefined(); expect(res.headers['x-ratelimit-reset']).toBeDefined(); expect(res.headers['ratelimit-limit']).toBeDefined(); expect(res.headers['ratelimit-remaining']).toBeDefined(); expect(res.headers['ratelimit-reset']).toBeDefined(); })); }); describe('Yanlış yapılandırma uyarı testi', () => { it('Eksik windowMs veya max ile başlatılırsa consola uyarı basılır', () => { const spy = jest.spyOn(console, 'warn').mockImplementation(() => { }); const app = (0, express_1.default)(); app.use((0, rateLimiter_1.rateLimiter)({ windowMs: 0, max: 0 })); expect(spy).toHaveBeenCalled(); spy.mockRestore(); }); }); describe('DummyStore ile temel limitleme', () => { it('DummyStore ile her zaman limit aşılmaz', () => __awaiter(void 0, void 0, void 0, function* () { const app = (0, express_1.default)(); const dummyStore = new dummyStore_1.DummyStore(); app.use((0, rateLimiter_1.rateLimiter)({ windowMs: 1000, max: 1 }, dummyStore)); app.get('/api', (_req, res) => res.send('ok')); for (let i = 0; i < 5; i++) { yield (0, supertest_1.default)(app).get('/api').expect(200); } })); });