ioredis-ratelimit
v2.3.0
Published
Generic ratelimit tool on top of ioredis.
Downloads
241
Readme
ioredis-ratelimit
Generic rate limiter on top of ioredis.
Supports
- Minimal difference between requests.
- Batch actions.
- Three levels of gratuitousness towards capped attempts.
Install
$ npm i ioredis-ratelimit --save
Usage
var ratelimit = require('ioredis-ratelimit')(options);
ratelimit().then(...).catch(...); // when key is string
ratelimit(id).then(...).catch(...); // when key is function
ratelimit(id, numActions).then(...).catch(...); // when key is function and batch actions are requested
ratelimit(numActions).then(...).catch(...); // when key is string
ratelimit.get().then(...); // return current size
Options
- client: {Object} client of ioredis.
- limit: {Number} max amount of calls in duration, default
1
. - duration: {Number} duration in millisecond, default
1000
. - difference: {Number} duration between each operation in millisecond, default
0
. - key: {String|Function} ratelimiter's key.
- mode: {String}
binary
,nary
, anduniform
, defaultbinary
. - error: {Error} throw when reach limit.
Examples
simple:
var Redis = require('ioredis');
var ratelimit = require('ioredis-ratelimit')({
client: new Redis(),
key: 'limiter',
limit: 3,
duration: 1000,
difference: 0, // allow no interval between requests
});
ratelimit().then(console.log).catch(console.error); // { total: 3, remaining: 2 }
ratelimit().then(console.log).catch(console.error); // { total: 3, remaining: 1 }
ratelimit().then(console.log).catch(console.error); // { total: 3, remaining: 0 }
ratelimit().then(console.log).catch(console.error); // 429 - [Error: Exceeded the limit]
ratelimit.get().then(console.log) // { total: 3, remaining: 0, retryAfterMS: 1000 }
Express:
'use strict';
var app = require('express')();
var Redis = require('ioredis');
var ratelimit = require('ioredis-ratelimit')({
client: new Redis(),
key: function (req) {
return 'limiter:' + req.user._id;
},
// 10 requests are allowed in 1s
limit: 10,
duration: 1000,
// there should be at least 10ms interval between requests
difference: 10,
});
// ...
app.use(function (req, res, next) {
ratelimit(req)
.then(function () {
next();
})
.catch(next);
});
app.get('/', function () {});
// ...
Batch actions
Binary
Binary mode is as straightforward as any other rate limiter.
var ratelimit = require('ioredis-ratelimit')({
client: new Redis(),
key: 'limiter',
limit: 5,
duration: 3000,
mode: 'binary',
error: new Error('Exceeded the limit')
});
ratelimit(2).then(console.log).catch(console.error); // { total: 2, acknowledged: 2, remaining: 3 }
ratelimit(2).then(console.log).catch(console.error); // { total: 4, acknowledged: 2, remaining: 1 }
ratelimit(2).then(console.log).catch(console.error); // 429 - [Error: Exceeded the limit]
N-ary
N-ary mode will try the best to fill up the bucket where partial saves are possible.
var ratelimit = require('ioredis-ratelimit')({
client: new Redis(),
key: 'limiter',
limit: 5,
duration: 3000,
mode: 'nary',
error: new Error('Exceeded the limit')
});
ratelimit(2).then(console.log).catch(console.error); // { total: 2, acknowledged: 2, remaining: 3 }
ratelimit(2).then(console.log).catch(console.error); // { total: 4, acknowledged: 2, remaining: 1 }
ratelimit(2).then(console.log).catch(console.error); // { total: 5, acknowledged: 1, remaining: 0 }
ratelimit(2).then(console.log).catch(console.error); // 429 - [Error: Exceeded the limit]
Uniform
Uniform mode will save all attempts when there's at least one slot.
var ratelimit = require('ioredis-ratelimit')({
client: new Redis(),
key: 'limiter',
limit: 5,
duration: 3000,
mode: 'uniform',
error: new Error('Exceeded the limit')
});
ratelimit(2).then(console.log).catch(console.error); // { total: 2, acknowledged: 2, remaining: 3 }
ratelimit(2).then(console.log).catch(console.error); // { total: 4, acknowledged: 2, remaining: 1 }
ratelimit(2).then(console.log).catch(console.error); // { total: 6, acknowledged: 2, remaining: 0 }
ratelimit(2).then(console.log).catch(console.error); // 429 - [Error: Exceeded the limit]
Test
$ npm test
License
MIT