Skip to content

Commit 7007ab0

Browse files
committed
Handle errors from redis store in request rate limit
1 parent 30bac65 commit 7007ab0

File tree

1 file changed

+30
-25
lines changed

1 file changed

+30
-25
lines changed

src/middleware/requestRateLimit.ts

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,42 @@
11
import { getIP } from "../utils/getIP";
22
import { getHash } from "../utils/getHash";
33
import { getHashCache } from "../utils/getHashCache";
4-
import rateLimit, { RateLimitRequestHandler } from "express-rate-limit";
4+
import rateLimit from "express-rate-limit";
55
import { RateLimitConfig } from "../types/config.model";
6-
import { Request } from "express";
6+
import { Request, RequestHandler } from "express";
77
import { isUserVIP } from "../utils/isUserVIP";
88
import { UserID } from "../types/user.model";
99
import RedisStore, { RedisReply } from "rate-limit-redis";
1010
import redis from "../utils/redis";
1111
import { config } from "../config";
1212
import { Logger } from "../utils/logger";
1313

14-
export function rateLimitMiddleware(limitConfig: RateLimitConfig, getUserID?: (req: Request) => UserID): RateLimitRequestHandler {
15-
return rateLimit({
16-
windowMs: limitConfig.windowMs,
17-
max: limitConfig.max,
18-
message: limitConfig.message,
19-
statusCode: limitConfig.statusCode,
20-
legacyHeaders: false,
21-
standardHeaders: false,
22-
keyGenerator: (req) => {
23-
return getHash(getIP(req), 1);
24-
},
25-
// eslint-disable-next-line @typescript-eslint/no-misused-promises
26-
handler: async (req, res, next) => {
27-
if (getUserID === undefined || !await isUserVIP(await getHashCache(getUserID(req)))) {
28-
return res.status(limitConfig.statusCode).send(limitConfig.message);
29-
} else {
30-
return next();
31-
}
32-
},
33-
store: config.redis?.enabled ? new RedisStore({
34-
sendCommand: (...args: string[]) => redis.sendCommand(args).catch((err) => Logger.error(err)) as Promise<RedisReply>,
35-
}) : null,
36-
});
14+
export function rateLimitMiddleware(limitConfig: RateLimitConfig, getUserID?: (req: Request) => UserID): RequestHandler {
15+
try {
16+
return rateLimit({
17+
windowMs: limitConfig.windowMs,
18+
max: limitConfig.max,
19+
message: limitConfig.message,
20+
statusCode: limitConfig.statusCode,
21+
legacyHeaders: false,
22+
standardHeaders: false,
23+
keyGenerator: (req) => {
24+
return getHash(getIP(req), 1);
25+
},
26+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
27+
handler: async (req, res, next) => {
28+
if (getUserID === undefined || !await isUserVIP(await getHashCache(getUserID(req)))) {
29+
return res.status(limitConfig.statusCode).send(limitConfig.message);
30+
} else {
31+
return next();
32+
}
33+
},
34+
store: config.redis?.enabled ? new RedisStore({
35+
sendCommand: (...args: string[]) => redis.sendCommand(args).catch((err) => Logger.error(err)) as Promise<RedisReply>,
36+
}) : null,
37+
});
38+
} catch (e) {
39+
Logger.error(`Rate limit error: ${e}`);
40+
return (req, res, next) => next();
41+
}
3742
}

0 commit comments

Comments
 (0)