lightweight-api-rate-limiter
Version:
A robust, framework-agnostic rate limiter for Node.js applications, built for scalability and ease of use
92 lines (70 loc) • 2.96 kB
JavaScript
const express = require('express');
const request = require('supertest');
const rateLimiter = require('../src/index');
describe('Rate Limiter Integration Tests', () => {
let app;
// Helper function to create a new Express app with the rate limiter
const createApp = (options) => {
const app = express();
app.use(rateLimiter(options));
app.get('/', (req, res) => res.send('OK'));
return app;
};
beforeEach(() => {
jest.useFakeTimers(); // Use fake timers to control time
});
afterEach(() => {
jest.useRealTimers(); // Reset to real timers after each test
});
test('allows requests under the limit', async () => {
app = createApp({ max: 2, windowMs: 1000 });
const res1 = await request(app).get('/');
expect(res1.status).toBe(200);
expect(res1.text).toBe('OK');
const res2 = await request(app).get('/');
expect(res2.status).toBe(200);
expect(res2.text).toBe('OK');
});
test('blocks requests over the limit', async () => {
app = createApp({ max: 2, windowMs: 1000 });
await request(app).get('/'); // 1st request
await request(app).get('/'); // 2nd request
const res = await request(app).get('/'); // 3rd request
expect(res.status).toBe(429);
expect(res.text).toBe('Too Many Requests');
expect(res.headers['x-ratelimit-limit']).toBe('2');
expect(res.headers['x-ratelimit-remaining']).toBe('0');
});
test('resets limit after window expires', async () => {
app = createApp({ max: 1, windowMs: 1000 });
await request(app).get('/'); // 1st request (OK)
let res = await request(app).get('/'); // 2nd request (blocked)
expect(res.status).toBe(429);
jest.advanceTimersByTime(1000); // Move time forward by 1 second
res = await request(app).get('/'); // Should work again
expect(res.status).toBe(200);
});
test('allows burst requests', async () => {
app = createApp({ max: 1, burstMax: 1, windowMs: 1000, burstWindowMs: 500 });
const res1 = await request(app).get('/'); // Base limit
expect(res1.status).toBe(200);
const res2 = await request(app).get('/'); // Burst limit
expect(res2.status).toBe(200);
const res3 = await request(app).get('/'); // Over limit
expect(res3.status).toBe(429);
expect(res3.headers['x-ratelimit-limit']).toBe('2'); // max + burstMax
});
test('respects whitelist', async () => {
app = createApp({ max: 1, windowMs: 1000, whitelist: ['127.0.0.1'] });
const res1 = await request(app).get('/'); // 1st request
const res2 = await request(app).get('/'); // 2nd request (normally blocked)
expect(res1.status).toBe(200);
expect(res2.status).toBe(200); // Whitelisted, so not blocked
});
test('blocks blacklist', async () => {
app = createApp({ max: 10, windowMs: 1000, blacklist: ['127.0.0.1'] });
const res = await request(app).get('/');
expect(res.status).toBe(403);
expect(res.text).toBe('Forbidden');
});
});