rate-limiter-flexible
Advanced tools
Comparing version 0.9.3 to 0.10.0
@@ -5,3 +5,3 @@ ## RateLimiterMongo | ||
Endpoint is pure NodeJS endpoint launched in `node:latest` and `redis:alpine` Docker containers with 4 workers | ||
Endpoint is pure NodeJS endpoint launched in `node:latest` and `mongo:jessie` Docker containers with 4 workers | ||
@@ -55,3 +55,3 @@ Endpoint is limited by `RateLimiterMongo` with config: | ||
It processes 10k, 100k and 250k requests for 10k random keys. | ||
It processes 10k, 100k and 250k writes for 10k random keys for: | ||
@@ -74,2 +74,2 @@ #### MongoDB default settings | ||
It is about 5% faster with disabled fsync and journaling, but avoiding extra disk I/O is worth. | ||
It is about 5% faster with disabled fsync and journaling, but avoiding extra disk I/O is worth. |
{ | ||
"name": "rate-limiter-flexible", | ||
"version": "0.9.3", | ||
"version": "0.10.0", | ||
"description": "Flexible API rate limiter backed by Redis for distributed node.js applications", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
100
README.md
@@ -9,2 +9,4 @@ [![Build Status](https://travis-ci.org/animir/node-rate-limiter-flexible.png)](https://travis-ci.org/animir/node-rate-limiter-flexible) | ||
<img src="rlflx-logo-small.png" width="50" alt="Logo"/> | ||
## node-rate-limiter-flexible | ||
@@ -29,2 +31,14 @@ | ||
### Links | ||
* [RateLimiterRedis](#ratelimiterredis) | ||
* [RateLimiterMongo](#ratelimitermongo) | ||
* [RateLimiterCluster](#ratelimitercluster) | ||
* [RateLimiterMemory](#ratelimitermemory) | ||
* [RateLimiterUnion](#ratelimiterunion) Combine 2 or more limiters to act as single | ||
* [Express middleware](#express-middleware) | ||
* [Koa middleware](#koa-middleware) | ||
* [Options](#options) | ||
* [API](#api) | ||
### Benchmark | ||
@@ -247,2 +261,72 @@ | ||
### RateLimiterUnion | ||
Combine 2 or more rate limiters to act as single | ||
Any rate limiters from this `rate-limiter-flexible` can be united | ||
Useful for authorization, which must be protected from password brute force | ||
For example, not more than once per second and only 5 points per minute | ||
`keyPrefix` is necessary as resolved and rejected results depend on it | ||
```javascript | ||
const limiter1 = new RateLimiterMemory({ | ||
keyPrefix: 'limit1', | ||
points: 1, | ||
duration: 1, | ||
}); | ||
const limiter2 = new RateLimiterMemory({ | ||
keyPrefix: 'limit2', | ||
points: 5, | ||
duration: 60, | ||
}); | ||
const rateLimiterUnion = new RateLimiterUnion(limiter1, limiter2); | ||
rateLimiterUnion.consume(remoteAddress) | ||
.then((res) => { | ||
// Returns object with 2 RateLimiterRes objects | ||
res['limit1'].remainingPoints; | ||
res['limit2'].remainingPoints; | ||
}) | ||
.catch((rej) => { | ||
/* Returns object with RateLimiterRes objects only for rejected limiters | ||
* For example: | ||
* { limit1: RateLimiterRes { ... } } | ||
* | ||
* It may be Error if you use Redis, Mongo or Cluster without insurance | ||
* { limit2: Error } | ||
*/ | ||
}); | ||
``` | ||
### Express middleware | ||
```javascript | ||
const rateLimiterMiddleware = (req, res, next) => { | ||
rateLimiter.consume(req.connection.remoteAddress) | ||
.then(() => { | ||
next(); | ||
}) | ||
.catch((rejRes) => { | ||
res.status(429).send('Too Many Requests'); | ||
}); | ||
}; | ||
``` | ||
### Koa middleware | ||
```javascript | ||
app.use(async (ctx, next) => { | ||
try { | ||
await rateLimiter.consume(ctx.ip) | ||
next() | ||
} catch (rejRes) { | ||
ctx.status = 429 | ||
ctx.body = 'Too Many Requests' | ||
} | ||
}) | ||
``` | ||
## Options | ||
@@ -299,3 +383,3 @@ | ||
} | ||
```` | ||
``` | ||
@@ -306,4 +390,4 @@ ### rateLimiter.consume(key, points = 1) | ||
* **resolved** with `RateLimiterRes` when point(s) is consumed, so action can be done | ||
* only for RateLimiterRedis if `insuranceLimiter` isn't setup: **rejected** when some Redis error happened, where reject reason `rejRes` is Error object | ||
* only for RateLimiterCluster: **rejected** when `timeoutMs` exceeded, where reject reason `rejRes` is Error object | ||
* **rejected** only for Redis and Mongo if `insuranceLimiter` isn't setup: when some error happened, where reject reason `rejRes` is Error object | ||
* **rejected** only for RateLimiterCluster if `insuranceLimiter` isn't setup: when `timeoutMs` exceeded, where reject reason `rejRes` is Error object | ||
* **rejected** when there is no points to be consumed, where reject reason `rejRes` is `RateLimiterRes` object | ||
@@ -324,5 +408,4 @@ * **rejected** when key is blocked (if block strategy is set up), where reject reason `rejRes` is `RateLimiterRes` object | ||
* **resolved** with `RateLimiterRes` | ||
* only for RateLimiterRedis if `insuranceLimiter` isn't setup: | ||
**rejected** when some Redis error happened, where reject reason `rejRes` is Error object | ||
* only for RateLimiterCluster: **rejected** when `timeoutMs` exceeded, where reject reason `rejRes` is Error object | ||
* **rejected** only for Redis and Mongo if `insuranceLimiter` isn't setup: when some error happened, where reject reason `rejRes` is Error object | ||
* **rejected** only for RateLimiterCluster if `insuranceLimiter` isn't setup: when `timeoutMs` exceeded, where reject reason `rejRes` is Error object | ||
@@ -337,5 +420,4 @@ ### rateLimiter.reward(key, points = 1) | ||
* **resolved** with `RateLimiterRes` | ||
* only for RateLimiterRedis if `insuranceLimiter` isn't setup: | ||
**rejected** when some Redis error happened, where reject reason `rejRes` is Error object | ||
* only for RateLimiterCluster: **rejected** when `timeoutMs` exceeded, where reject reason `rejRes` is Error object | ||
* **rejected** only for RateLimiterRedis if `insuranceLimiter` isn't setup: when some Redis error happened, where reject reason `rejRes` is Error object | ||
* **rejected** only for RateLimiterCluster if `insuranceLimiter` isn't setup: when `timeoutMs` exceeded, where reject reason `rejRes` is Error object | ||
@@ -342,0 +424,0 @@ ## Contribution |
Sorry, the diff of this file is not supported yet
112686
28
882
424