@gssjsbs/rate-limiter
v0.1.0
Published
Configurable rate limiting for APIs
Downloads
62
Readme
@gssjsbs/rate-limiter
Configurable rate limiting middleware for APIs. Supports sliding window algorithm with in-memory store.
Installation
npm install @gssjsbs/rate-limiterQuick Start
Express
import express from 'express';
import { createRateLimiter } from '@gssjsbs/rate-limiter';
const app = express();
const limiter = createRateLimiter({
maxRequests: 100,
windowMs: 15 * 60 * 1000, // 15 minutes
keyBy: 'ip'
});
app.use(limiter.middleware);
app.get('/api/data', (req, res) => {
res.json({ message: 'Success' });
});Next.js (App Router)
import { createRateLimiter } from '@gssjsbs/rate-limiter';
import { NextResponse } from 'next/server';
const limiter = createRateLimiter({
maxRequests: 50,
windowMs: 60 * 1000, // 1 minute
keyBy: 'ip'
});
export async function GET(request: Request) {
const result = await limiter.nextHandler(request);
if (!result.allowed) {
return NextResponse.json(
{ error: result.error?.message },
{ status: result.error?.statusCode, headers: result.headers }
);
}
return NextResponse.json({ message: 'Success' }, { headers: result.headers });
}Fastify
import Fastify from 'fastify';
import { createRateLimiter } from '@gssjsbs/rate-limiter';
const fastify = Fastify();
const limiter = createRateLimiter({
maxRequests: 100,
windowMs: 15 * 60 * 1000,
keyBy: 'ip'
});
fastify.addHook('onRequest', limiter.fastifyHook);
fastify.get('/api/data', async (request, reply) => {
return { message: 'Success' };
});Configuration
| Option | Type | Required | Default | Description |
|--------|------|----------|---------|-------------|
| maxRequests | number | Yes | 100 | Max requests allowed per window |
| windowMs | number | Yes | - | Time window in milliseconds |
| keyBy | 'ip' \| 'userId' \| 'apiKey' \| 'custom' | No | 'ip' | How to identify clients |
| message | string | No | 'Too many requests...' | Custom rate limit message |
| statusCode | number | No | 429 | HTTP status code when blocked |
| skipFailedRequests | boolean | No | false | Skip counting 4xx/5xx responses |
| store | 'memory' \| 'redis' | No | 'memory' | Storage backend |
| customKeyFn | (req) => string | No | - | Custom key extraction function |
API
createRateLimiter(config)
Returns a rate limiter instance with the following methods:
| Method | Description |
|--------|-------------|
| check(identifier) | Check if request is allowed. Returns { allowed, remaining, limit, resetTime, message, statusCode } |
| getInfo(identifier) | Get current rate limit info without consuming a request |
| reset(identifier) | Reset counter for a specific identifier |
| resetAll() | Reset all counters |
| middleware | Express middleware |
| nextHandler | Next.js route handler wrapper |
| fastifyHook | Fastify onRequest hook |
Response Headers
All adapters automatically set these headers:
X-RateLimit-Limit- Maximum requests allowedX-RateLimit-Remaining- Remaining requests in current windowX-RateLimit-Reset- Unix timestamp when the window resetsRetry-After- Seconds to wait (only when rate limited)
Advanced Usage
Custom Key Extraction
const limiter = createRateLimiter({
maxRequests: 100,
windowMs: 15 * 60 * 1000,
keyBy: 'custom',
customKeyFn: (req) => req.headers['x-tenant-id'] || req.ip
});Manual Check (Framework-Agnostic)
const limiter = createRateLimiter({
maxRequests: 10,
windowMs: 60000
});
const result = limiter.check('user-123');
if (!result.allowed) {
console.log(`Rate limited. Retry after ${result.resetTime}`);
}TypeScript
Full TypeScript support with auto-completed config options and typed responses.
import type { RateLimiterConfig, RateLimitResult } from '@gssjsbs/rate-limiter';
const config: RateLimiterConfig = {
maxRequests: 50,
windowMs: 60000
};License
MIT
