Gathering detailed insights and metrics for @fuechschen/rolling-rate-limiter
Gathering detailed insights and metrics for @fuechschen/rolling-rate-limiter
npm install @fuechschen/rolling-rate-limiter
Typescript
Module System
Node Version
NPM Version
72.1
Supply Chain
98.9
Quality
74.6
Maintenance
100
Vulnerability
99.6
License
Total Downloads
640
Last Day
3
Last Week
4
Last Month
11
Last Year
67
Minified
Minified + Gzipped
Latest Version
0.1.10
Package Id
@fuechschen/rolling-rate-limiter@0.1.10
Unpacked Size
27.26 kB
Size
6.38 kB
File Count
8
NPM Version
5.6.0
Node Version
10.0.0
Cumulative downloads
Total Downloads
Last day
0%
3
Compared to previous day
Last week
300%
4
Compared to previous week
Last month
266.7%
11
Compared to previous month
Last year
-43.7%
67
Compared to previous year
2
This is an implementation of a rate limiter in node.js that allows for rate limiting with a rolling window.
This means that if a user is allowed 5 actions per 60 seconds, any action will be blocked if 5 actions have already occured in the preceeding 60 seconds, without any set points at which this interval resets. This contrasts with many existing implementations, in which a user could make 5 requests at 0:59 and another 5 requests at 1:01.
It can use either in-memory storage or Redis as a backend. If Redis is used, multiple rate limiters can share one instance with different namespaces, and multiple processes can share rate limiter state safely without race conditions. The implementation uses what I believe to be a novel algorithm, with sorted sets.
1 2 /* 3 Setup: 4 */ 5 6 var RateLimiter = require("rolling-rate-limiter"); 7 8 var limiter = RateLimiter({ 9 interval: 1000 // in miliseconds 10 maxInInterval: 10, 11 minDifference: 100 // optional: the minimum time (in miliseconds) between any two actions 12 }); 13 14 /* 15 Action: 16 */ 17 18 function attemptAction(userId) { 19 20 // Argument should be a unique identifier for a user if one exists. 21 // If none is provided, the limiter will not differentiate between users. 22 var timeLeft = limiter(userId) 23 24 if (timeLeft > 0) { 25 26 // limit was exceeded, action should not be allowed 27 // timeLeft is the number of ms until the next action will be allowed 28 // note that this can be treated as a boolean, since 0 is falsy 29 30 } else { 31 32 // limit was not exceeded, action should be allowed 33 34 } 35 36 } 37 38 /* 39 Note that the in-memory version can also operate asynchronously. 40 The syntax is identical to the redis implementation below. 41 */
This allows multiple processes (e.g. multiple instances of a server application) to use a single redis to share rate limiter state. Make sure that the limiters have identical configurations in each instance.
1 2 /* 3 Setup: 4 */ 5 6 var RateLimiter = require("rolling-rate-limiter"); 7 var Redis = require("redis"); 8 var client = Redis.createClient(config); 9 10 var limiter = RateLimiter({ 11 redis: client, 12 namespace: "UserLoginLimiter", // optional: allows one redis instance to handle multiple types of rate limiters. defaults to "rate-limiter-{string of 8 random characters}" 13 interval: 1000, 14 maxInInterval: 10, 15 minDifference: 100 16 }); 17 18 /* 19 Action: 20 */ 21 22 function attemptAction(userId, cb) { 23 limiter(userId, function(err, timeLeft, actionsLeft) { 24 if (err) { 25 // redis failed or similar. 26 } else if (timeLeft) { 27 // limit was exceeded, action should not be allowed 28 } else { 29 // limit was not exceeded, action should be allowed 30 } 31 }); 32 } 33
You can easily use this module to set up a request rate limiter middleware in Express.
1 var limiter = RateLimiter({ 2 redis: redisClient, 3 namespace: "requestRateLimiter", 4 interval: 60000, 5 maxInInterval: 100, 6 minDifference: 100 7 }); 8 9 app.use(function(req, res, next) { 10 11 // "req.ipAddress" could be replaced with any unique user identifier 12 // Note that the limiter returns the number of miliseconds until an action 13 // will be allowed. Since 0 is falsey, this can be treated as a boolean. 14 limiter(req.ipAddress, function(err, timeLeft) { 15 if (err) { 16 return res.status(500).send(); 17 } else if (timeLeft) { 18 return res.status(429).send("You must wait " + timeLeft + " ms before you can make requests."); 19 } else { 20 return next(); 21 } 22 }); 23 24 });
No vulnerabilities found.
No security vulnerabilities found.