@developers-joyride/rate-limiter
Version:
A flexible rate limiting library with TypeScript support, Express middleware, and NestJS guard/interceptor capabilities
106 lines (105 loc) • 3.82 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RateLimiterService = void 0;
const mongodb_cache_provider_1 = require("../providers/mongodb-cache.provider");
const redis_cache_provider_1 = require("../providers/redis-cache.provider");
class RateLimiterService {
constructor(config) {
this.isInitialized = false;
this.config = {
cacheProvider: {
type: config.cacheProvider.type,
collectionName: config.cacheProvider.collectionName || "rateLimitingLogs",
redisKeyPrefix: config.cacheProvider.redisKeyPrefix || "rate_limit:",
mongoUrl: config.cacheProvider.mongoUrl,
redisUrl: config.cacheProvider.redisUrl,
},
keyGenerator: config.keyGenerator ||
((req) => req.ip || req.connection.remoteAddress || "unknown"),
errorMessage: config.errorMessage || "Too many requests, please try again later.",
includeHeaders: config.includeHeaders !== undefined ? config.includeHeaders : true,
statusCode: config.statusCode || 429,
maxRequests: config.maxRequests,
windowMs: config.windowMs,
};
// Initialize the appropriate cache provider
if (this.config.cacheProvider.type === "mongodb") {
if (!this.config.cacheProvider.mongoUrl) {
throw new Error("MongoDB URL is required when using MongoDB cache provider");
}
this.cacheProvider = new mongodb_cache_provider_1.MongoDBCacheProvider(this.config.cacheProvider);
}
else if (this.config.cacheProvider.type === "redis") {
if (!this.config.cacheProvider.redisUrl) {
throw new Error("Redis URL is required when using Redis cache provider");
}
this.cacheProvider = new redis_cache_provider_1.RedisCacheProvider(this.config.cacheProvider);
}
else {
throw new Error(`Unsupported cache provider type: ${this.config.cacheProvider.type}`);
}
}
/**
* Initialize the cache provider
*/
async initialize() {
if (this.isInitialized) {
return;
}
try {
await this.cacheProvider.initialize();
this.isInitialized = true;
console.log("Rate limiter service initialized successfully");
}
catch (error) {
console.error("Failed to initialize rate limiter service:", error);
throw error;
}
}
/**
* Check if a request is allowed based on rate limiting rules
*/
async checkLimit(req) {
await this.ensureInitialized();
const key = this.config.keyGenerator(req);
return await this.cacheProvider.checkLimit(key, this.config.maxRequests, this.config.windowMs);
}
/**
* Reset rate limit for a specific key
*/
async resetLimit(key) {
await this.ensureInitialized();
await this.cacheProvider.resetLimit(key);
}
/**
* Get current rate limit info for a key
*/
async getLimitInfo(key) {
await this.ensureInitialized();
return await this.cacheProvider.getLimitInfo(key);
}
/**
* Ensure cache provider is initialized
*/
async ensureInitialized() {
if (!this.isInitialized) {
await this.initialize();
}
}
/**
* Close the cache provider connection
*/
async close() {
if (this.isInitialized) {
await this.cacheProvider.close();
this.isInitialized = false;
}
}
/**
* Get the current configuration
*/
getConfig() {
return { ...this.config };
}
}
exports.RateLimiterService = RateLimiterService;