JS
S
JavaScriptThis resource provides essential guidance on implementing rate limiting in Express.js applications. Learn how to protect your Node.js servers from DDoS attacks and excessive requests, ensuring optimal performance and security. Discover best practices aligned with IETF standards for efficient API management and traffic control.
1import redis from 'redis';
2import { RateLimiterRedis, RateLimiterRes } from 'rate-limiter-flexible';
3
4import { MemoryCache } from './memory-cache';
5import logService from './log';
6
7const options = {
8 storeClient: MemoryCache.redisClient,
9 keyPrefix: 'middleware',
10 points: 15, // 10 requests
11 duration: 1, // per 1 second by IP
12};
13
14const rateLimiter = new RateLimiterRedis(options);
15
16const rateLimiterRedisMiddleware = (req: any, res: any, next: any) => {
17 logService.log('debug', 'rateLimiterRedisMiddleware', { status: 'PROCESSING' });
18 if (!MemoryCache.redisClient.connected) {
19 logService.log('error', 'rateLimiterRedisMiddleware', { status: 'REDIS_FAIL_BYPASS' });
20 return next();
21 }
22 rateLimiter
23 .consume(req.ip)
24 .then((rateLimiterRes: RateLimiterRes) => {
25 logService.log('debug', 'rateLimiterRedisMiddleware', { status: 'OK' });
26 const headers = {
27 'Retry-After': rateLimiterRes.msBeforeNext / 1000,
28 'X-RateLimit-Limit': options.points,
29 'X-RateLimit-Remaining': rateLimiterRes.remainingPoints,
30 'X-RateLimit-Reset': new Date(Date.now() + rateLimiterRes.msBeforeNext),
31 };
32 res.set(headers);
33 next();
34 })
35 .catch((rateLimiterRes: RateLimiterRes) => {
36 logService.log('error', 'rateLimiterRedisMiddleware', { status: 'BLOCK', rateLimiterRes });
37 const headers = {
38 'Retry-After': rateLimiterRes.msBeforeNext / 1000,
39 'X-RateLimit-Limit': options.points,
40 'X-RateLimit-Remaining': rateLimiterRes.remainingPoints,
41 'X-RateLimit-Reset': new Date(Date.now() + rateLimiterRes.msBeforeNext),
42 };
43 res.set(headers);
44 res.status(429).send('Too Many Requests');
45 });
46};
47
48export default rateLimiterRedisMiddleware;
49Created on 1/17/2021