summary refs log tree commit diff
path: root/src/middlewares/RateLimit.ts
diff options
context:
space:
mode:
authorFlam3rboy <34555296+Flam3rboy@users.noreply.github.com>2021-07-01 21:27:46 +0200
committerFlam3rboy <34555296+Flam3rboy@users.noreply.github.com>2021-07-01 21:27:46 +0200
commitc3c8026041d29d7b50d54080d21518cadae97fff (patch)
tree3c95d992accbc99624d5a6dcc7ec946f56e48697 /src/middlewares/RateLimit.ts
parentMerge pull request #162 from fosscord/feat--rate-limit (diff)
downloadserver-c3c8026041d29d7b50d54080d21518cadae97fff.tar.xz
:sparkles: route specific rate limits
Diffstat (limited to 'src/middlewares/RateLimit.ts')
-rw-r--r--src/middlewares/RateLimit.ts36
1 files changed, 21 insertions, 15 deletions
diff --git a/src/middlewares/RateLimit.ts b/src/middlewares/RateLimit.ts

index 93d69236..89e002df 100644 --- a/src/middlewares/RateLimit.ts +++ b/src/middlewares/RateLimit.ts
@@ -36,17 +36,21 @@ export default function RateLimit(opts: { window: number; count: number; bot?: number; - error?: number; webhook?: number; oauth?: number; GET?: number; MODIFY?: number; + error?: boolean; + success?: boolean; + onylIp?: boolean; }) { Cache.init(); // will only initalize it once return async (req: Request, res: Response, next: NextFunction) => { - const bucket_id = opts.bucket || req.path.replace(API_PREFIX_TRAILING_SLASH, ""); - const user_id = req.user_id || getIpAdress(req); + const bucket_id = opts.bucket || req.originalUrl.replace(API_PREFIX_TRAILING_SLASH, ""); + var user_id = getIpAdress(req); + if (!opts.onylIp && req.user_id) user_id = req.user_id; + var max_hits = opts.count; if (opts.bot && req.user_bot) max_hits = opts.bot; if (opts.GET && ["GET", "OPTIONS", "HEAD"].includes(req.method)) max_hits = opts.GET; @@ -59,9 +63,9 @@ export default function RateLimit(opts: { const resetAfterMs = reset - Date.now(); const resetAfterSec = resetAfterMs / 1000; const global = bucket_id === "global"; - console.log("blocked", { resetAfterMs }); if (resetAfterMs > 0) { + console.log("blocked", { resetAfterMs }); return ( res .status(429) @@ -76,26 +80,28 @@ export default function RateLimit(opts: { .send({ message: "You are being rate limited.", retry_after: resetAfterSec, global }) ); } else { + offender.hits = 0; + offender.expires_at = new Date(Date.now() + opts.window * 1000); + offender.blocked = false; // mongodb ttl didn't update yet -> manually update/delete - db.collection("ratelimits").updateOne( - { id: bucket_id, user_id }, - { $set: { hits: 0, expires_at: new Date(Date.now() + opts.window * 1000), blocked: false } } - ); + db.collection("ratelimits").updateOne({ id: bucket_id, user_id }, { $set: offender }); } } next(); + const hitRouteOpts = { bucket_id, user_id, max_hits, window: opts.window }; - if (opts.error) { + if (opts.error || opts.success) { res.once("finish", () => { // check if error and increment error rate limit - if (res.statusCode >= 400) { - // TODO: use config rate limit values - return hitRoute({ bucket_id: "error", user_id, max_hits: opts.error as number, window: opts.window }); + if (res.statusCode >= 400 && opts.error) { + return hitRoute(hitRouteOpts); + } else if (res.statusCode >= 200 && res.statusCode < 300 && opts.success) { + return hitRoute(hitRouteOpts); } }); + } else { + return hitRoute(hitRouteOpts); } - - return hitRoute({ user_id, bucket_id, max_hits, window: opts.window }); }; } @@ -121,7 +127,7 @@ function hitRoute(opts: { user_id: string; bucket_id: string; max_hits: number; { $set: { hits: { $sum: [{ $ifNull: ["$hits", 0] }, 1] }, - blocked: { $gt: ["$hits", opts.max_hits] } + blocked: { $gte: ["$hits", opts.max_hits] } } } ],