Skip to content

Commit 95b499f

Browse files
authored
fix: rate-limit when max is 0 (#652)
Signed-off-by: Bob Du <[email protected]>
1 parent 271a57c commit 95b499f

File tree

1 file changed

+35
-10
lines changed

1 file changed

+35
-10
lines changed

service/src/middleware/limiter.ts

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { RequestHandler } from 'express'
2+
import type { Options } from 'express-rate-limit'
13
import * as process from 'node:process'
24
import * as dotenv from 'dotenv'
35
import { rateLimit } from 'express-rate-limit'
@@ -9,15 +11,38 @@ dotenv.config()
911
const MAX_REQUEST_PER_HOUR = process.env.MAX_REQUEST_PER_HOUR
1012
const AUTH_MAX_REQUEST_PER_MINUTE = process.env.AUTH_MAX_REQUEST_PER_MINUTE
1113

12-
const maxCount = (isNotEmptyString(MAX_REQUEST_PER_HOUR) && !Number.isNaN(Number(MAX_REQUEST_PER_HOUR)))
13-
? Number.parseInt(MAX_REQUEST_PER_HOUR)
14-
: 0 // 0 means unlimited
15-
const authMaxCount = (isNotEmptyString(AUTH_MAX_REQUEST_PER_MINUTE) && !Number.isNaN(Number(AUTH_MAX_REQUEST_PER_MINUTE)))
16-
? Number.parseInt(AUTH_MAX_REQUEST_PER_MINUTE)
17-
: 0 // 0 means unlimited
18-
const limiter = rateLimit({
14+
function parsePositiveInt(value?: string | null): number | null {
15+
if (!isNotEmptyString(value)) {
16+
return null
17+
}
18+
19+
const parsedValue = Number.parseInt(value, 10)
20+
21+
return Number.isNaN(parsedValue) || parsedValue <= 0 ? null : parsedValue
22+
}
23+
24+
const noopLimiter: RequestHandler = (_req, _res, next) => {
25+
next()
26+
}
27+
28+
type LimiterOptions = Partial<Omit<Options, 'limit' | 'max'>>
29+
30+
function buildLimiter(
31+
count: number | null,
32+
options: LimiterOptions,
33+
): RequestHandler {
34+
if (!count) {
35+
return noopLimiter
36+
}
37+
38+
return rateLimit({
39+
...options,
40+
limit: count,
41+
})
42+
}
43+
44+
const limiter = buildLimiter(parsePositiveInt(MAX_REQUEST_PER_HOUR), {
1945
windowMs: 60 * 60 * 1000, // Maximum number of accesses within an hour
20-
max: maxCount,
2146
statusCode: 200, // 200 means success,but the message is 'Too many request from this IP in 1 hour'
2247
keyGenerator: (req, _) => {
2348
return requestIp.getClientIp(req) // IP address from requestIp.mw(), as opposed to req.ip
@@ -26,9 +51,9 @@ const limiter = rateLimit({
2651
res.send({ status: 'Fail', message: 'Too many request from this IP in 1 hour', data: null })
2752
},
2853
})
29-
const authLimiter = rateLimit({
54+
55+
const authLimiter = buildLimiter(parsePositiveInt(AUTH_MAX_REQUEST_PER_MINUTE), {
3056
windowMs: 60 * 1000, // Maximum number of accesses within a minute
31-
max: authMaxCount,
3257
statusCode: 200, // 200 means success,but the message is 'Too many request from this IP in 1 minute'
3358
keyGenerator: (req, _) => {
3459
return requestIp.getClientIp(req) // IP address from requestIp.mw(), as opposed to req.ip

0 commit comments

Comments
 (0)