Skip to content

Instantly share code, notes, and snippets.

@pipethedev
Created March 26, 2024 11:00
Show Gist options
  • Save pipethedev/cebd35211fee6dfd45561715aa64d440 to your computer and use it in GitHub Desktop.
Save pipethedev/cebd35211fee6dfd45561715aa64d440 to your computer and use it in GitHub Desktop.
import { container } from 'tsyringe';
import { RateLimiterRedis } from 'rate-limiter-flexible';
import httpStatus from 'http-status';
import ms from 'ms';
import { ErrorResponse } from '@shared/utils/response.util';
import { RedisClient } from '@shared/utils/redis/redis-client/redis-client';
import { RateLimitingConfig } from '@shared/types/general.type';
const redisClient = container.resolve(RedisClient).get();
const initRateLimiter = (rateLimitingConfig: RateLimitingConfig) => {
const rateLimiterRedis = new RateLimiterRedis({
storeClient: redisClient,
keyPrefix: 'rate-limiter',
points: rateLimitingConfig.maxRequests,
duration: ms(rateLimitingConfig.window) / 1000,
});
return async (req, res, next) => {
try {
await rateLimiterRedis.consume(req.headers?.authorization || req.headers['x-forwarded-for'] || req.socket?.remoteAddress);
return next();
} catch (err) {
const rlResIp = await rateLimiterRedis.get(req.headers?.authorization || req.headers['x-forwarded-for'] || req.socket.remoteAddress);
const retrySecs = Math.round(rlResIp.msBeforeNext / 1000) || 1;
res.send(ErrorResponse('Too many requests'), httpStatus.TOO_MANY_REQUESTS, { 'Retry-After': String(retrySecs) });
}
};
};
export default initRateLimiter;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment