|
1 | 1 | import { getIP } from "../utils/getIP";
|
2 | 2 | import { getHash } from "../utils/getHash";
|
3 | 3 | import { getHashCache } from "../utils/getHashCache";
|
4 |
| -import rateLimit, { RateLimitRequestHandler } from "express-rate-limit"; |
| 4 | +import rateLimit from "express-rate-limit"; |
5 | 5 | import { RateLimitConfig } from "../types/config.model";
|
6 |
| -import { Request } from "express"; |
| 6 | +import { Request, RequestHandler } from "express"; |
7 | 7 | import { isUserVIP } from "../utils/isUserVIP";
|
8 | 8 | import { UserID } from "../types/user.model";
|
9 | 9 | import RedisStore, { RedisReply } from "rate-limit-redis";
|
10 | 10 | import redis from "../utils/redis";
|
11 | 11 | import { config } from "../config";
|
12 | 12 | import { Logger } from "../utils/logger";
|
13 | 13 |
|
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 | + } |
37 | 42 | }
|
0 commit comments