brunner56's picture
implement app
0bfe2e3
import rateLimit from 'express-rate-limit';
import { Request, Response, NextFunction } from 'express';
import { Env, createLogger, constants, APIError } from '@aiostreams/core';
const logger = createLogger('ratelimit');
const createRateLimiter = (
windowMs: number,
maxRequests: number,
prefix: string = ''
) => {
if (Env.DISABLE_RATE_LIMITS) {
return (req: Request, res: Response, next: NextFunction) => next();
}
return rateLimit({
windowMs,
max: maxRequests,
standardHeaders: true,
legacyHeaders: false,
// Use a unique store key for each rate limiter
keyGenerator: (req: Request) => `${prefix}:${req.userIp || req.ip || ''}`,
handler: (
req: Request,
res: Response,
next: NextFunction,
options: any
) => {
const timeRemaining = req.rateLimit?.resetTime
? req.rateLimit.resetTime.getTime() - new Date().getTime()
: 0;
logger.warn(
`Rate limit exceeded for IP: ${req.userIp || req.ip} - ${
options.message
} - Time remaining: ${timeRemaining}ms`
);
throw new APIError(constants.ErrorCode.RATE_LIMIT_EXCEEDED);
},
});
};
const userApiRateLimiter = createRateLimiter(
Env.USER_API_RATE_LIMIT_WINDOW * 1000,
Env.USER_API_RATE_LIMIT_MAX_REQUESTS,
'user-api'
);
const streamApiRateLimiter = createRateLimiter(
Env.STREAM_API_RATE_LIMIT_WINDOW * 1000,
Env.STREAM_API_RATE_LIMIT_MAX_REQUESTS,
'stream-api'
);
const formatApiRateLimiter = createRateLimiter(
Env.FORMAT_API_RATE_LIMIT_WINDOW * 1000,
Env.FORMAT_API_RATE_LIMIT_MAX_REQUESTS,
'format-api'
);
const catalogApiRateLimiter = createRateLimiter(
Env.CATALOG_API_RATE_LIMIT_WINDOW * 1000,
Env.CATALOG_API_RATE_LIMIT_MAX_REQUESTS,
'catalog-api'
);
const stremioStreamRateLimiter = createRateLimiter(
Env.STREMIO_STREAM_RATE_LIMIT_WINDOW * 1000,
Env.STREMIO_STREAM_RATE_LIMIT_MAX_REQUESTS,
'stremio-stream'
);
const stremioCatalogRateLimiter = createRateLimiter(
Env.STREMIO_CATALOG_RATE_LIMIT_WINDOW * 1000,
Env.STREMIO_CATALOG_RATE_LIMIT_MAX_REQUESTS,
'stremio-catalog'
);
const stremioManifestRateLimiter = createRateLimiter(
Env.STREMIO_MANIFEST_RATE_LIMIT_WINDOW * 1000,
Env.STREMIO_MANIFEST_RATE_LIMIT_MAX_REQUESTS,
'stremio-manifest'
);
const stremioSubtitleRateLimiter = createRateLimiter(
Env.STREMIO_SUBTITLE_RATE_LIMIT_WINDOW * 1000,
Env.STREMIO_SUBTITLE_RATE_LIMIT_MAX_REQUESTS,
'stremio-subtitle'
);
const stremioMetaRateLimiter = createRateLimiter(
Env.STREMIO_META_RATE_LIMIT_WINDOW * 1000,
Env.STREMIO_META_RATE_LIMIT_MAX_REQUESTS,
'stremio-meta'
);
const staticRateLimiter = createRateLimiter(
Env.STATIC_RATE_LIMIT_WINDOW * 1000,
Env.STATIC_RATE_LIMIT_MAX_REQUESTS,
'static'
);
export {
userApiRateLimiter,
streamApiRateLimiter,
formatApiRateLimiter,
catalogApiRateLimiter,
stremioStreamRateLimiter,
stremioCatalogRateLimiter,
stremioManifestRateLimiter,
stremioSubtitleRateLimiter,
stremioMetaRateLimiter,
staticRateLimiter,
};