Created
May 3, 2024 06:50
-
-
Save chandelabhishek/6d6ddb818542078f13b95341423a4039 to your computer and use it in GitHub Desktop.
sliding window rate limter using redis and nodejs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * parameters for both functions: | |
| * 1. isOverTheLimit | |
| * 2. addRequestToRateLimitWndow | |
| * | |
| * is a key, which represents the key on which the rate limiter should be working. | |
| * e.g. | |
| * 1. if you want to rate limit a specific api, say, /v1/api then key is simply : `/v1/api` | |
| * 2. if you want to rate limit a specific api and IP address, then key can a combination of both viz.: `/v1/api:34.10.43.23` | |
| * | |
| * above can be extend to your usecase. | |
| * | |
| */ | |
| const { createClient } = require("redis"); | |
| const { v4 } = require("uuid"); | |
| const { REDIS_URL, RATE_LIMITER_WINDOW, RATE_LIMITER_MAX_ALLOWED_REQUESTS } = | |
| process.env; | |
| const slidingWindow = parseInt(RATE_LIMITER_WINDOW, 10); | |
| const maxRequests = parseInt(RATE_LIMITER_MAX_ALLOWED_REQUESTS, 10); | |
| function closeRedisConnection() { | |
| redis.quit(); | |
| } | |
| module.exports = async function getRateLimiter() { | |
| const redis = createClient({ url: REDIS_URL }); | |
| await redis.connect(); | |
| /** | |
| * | |
| * @returns boolean -- true/false based on if synthesia sign api can be called | |
| */ | |
| async function isOverTheLimit(key) { | |
| const currentTime = await redis.time(); | |
| const [_, cardinality] = await redis | |
| .multi() | |
| .zRemRangeByScore(key, 0, currentTime - slidingWindow) | |
| .zCard(key) | |
| .expire(key, Math.floor(slidingWindow / 1000)) | |
| .exec(); | |
| if (cardinality >= maxRequests) return true; | |
| return false; | |
| } | |
| /** | |
| * Increases the count of the request in the given window | |
| */ | |
| async function addRequestToRateLimitWndow(key) { | |
| const currentTime = await redis.time(); | |
| await redis.zAdd(key, { | |
| score: currentTime.getTime(), | |
| value: `${v4()}`, | |
| }); | |
| } | |
| return { isOverTheLimit, addRequestToRateLimitWndow }; | |
| }; | |
| process.on("cleanup", () => closeRedisConnection()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment