async-ratelimiter
Version:
Rate limit made simple, easy, async.
191 lines (126 loc) • 5.14 kB
Markdown
<div align="center">
<img src="https://github.com/microlinkhq/cdn/raw/master/dist/logo/banner.png#gh-light-mode-only" alt="microlink logo">
<img src="https://github.com/microlinkhq/cdn/raw/master/dist/logo/banner-dark.png#gh-dark-mode-only" alt="microlink logo">
<br>
<br>
</div>

[](https://coveralls.io/github/microlinkhq/async-ratelimiter)
[](https://www.npmjs.org/package/async-ratelimiter)
> Rate limit made simple, easy, async. Based on [ratelimiter](https://github.com/tj/node-ratelimiter).
```bash
$ npm install async-ratelimiter --save
```
The most straightforward way to use the rate limiter:
```js
'use strict'
const RateLimiter = require('async-ratelimiter')
const { getClientIp } = require('request-ip')
const Redis = require('ioredis')
const rateLimiter = new RateLimiter({
db: new Redis()
})
const apiQuota = async (req, res, next) => {
const clientIp = getClientIp(req)
const limit = await rateLimiter.get({ id: clientIp })
if (!res.writableEnded) {
res.setHeader('X-Rate-Limit-Limit', limit.total)
res.setHeader('X-Rate-Limit-Remaining', Math.max(0, limit.remaining - 1))
res.setHeader('X-Rate-Limit-Reset', limit.reset)
}
return !limit.remaining
? sendFail({
req,
res,
code: HTTPStatus.TOO_MANY_REQUESTS,
message: MESSAGES.RATE_LIMIT_EXCEDEED()
})
: next(req, res)
}
```
For scenarios where you want to check the limit status before consuming a request, you should to pass `{ peek: true }`:
```js
const apiQuota = async (req, res, next) => {
const clientIp = getClientIp(req)
// Check rate limit status without consuming a request
const status = await rateLimiter.get({ id: clientIp, peek: true })
if (status.remaining === 0) {
return sendFail({
req,
res,
code: HTTPStatus.TOO_MANY_REQUESTS,
message: MESSAGES.RATE_LIMIT_EXCEDEED()
})
}
// Consume a request
const limit = await rateLimiter.get({ id: clientIp })
if (!res.writableEnded) {
res.setHeader('X-Rate-Limit-Limit', limit.total)
res.setHeader('X-Rate-Limit-Remaining', limit.remaining)
res.setHeader('X-Rate-Limit-Reset', limit.reset)
}
return next(req, res)
}
```
It creates an rate limiter instance.
_Required_<br>
Type: `object`
The redis connection instance.
Type: `number`<br>
Default: `2500`
The maximum number of requests within `duration`.
Type: `number`<br>
Default: `3600000`
How long keep records of requests in milliseconds.
Type: `string`<br>
Default: `'limit'`
The prefix used for compound the key.
Type: `string`
The identifier to limit against (typically a user id).
You can pass this value using when you use `.get` method as well.
### .get(options)
Given an `id`, returns a Promise with the status of the limit with the following structure:
- `total`: `max` value.
- `remaining`: number of calls left in current `duration` without decreasing current `get`.
- `reset`: time since epoch in seconds that the rate limiting period will end (or already ended).
#### options
##### id
Type: `string`
Default: `this.id`
The identifier to limit against (typically a user id).
##### max
Type: `number`</br>
Default: `this.max`
The maximum number of requests within `duration`. If provided, it overrides the default `max` value. This is useful for custom limits that differ between IDs.
##### duration
Type: `number`</br>
Default: `this.duration`
How long keep records of requests in milliseconds. If provided, it overrides the default `duration` value.
##### peek
Type: `boolean`<br>
Default: `false`
When set to `true`, returns the current rate limit status **without consuming a request**. This is useful for checking the current rate limit status before deciding whether to proceed with an operation.
### defineCommand
It provides the command definition so you can load it into any [ioredis](https://github.com/redis/ioredis) instance:
```js
const Redis = require('ioredis')
const redis = new Redis(uri, {
scripts: { ...require('async-ratelimiter').defineCommand }
})
```
- [express-slow-down](https://github.com/nfriedly/express-slow-down) – Slow down repeated requests; use as an alternative (or addition) to express-rate-limit.
**async-ratelimiter** © [microlink.io](https://microlink.io), released under the [MIT](https://github.com/microlinkhq/async-ratelimiter/blob/master/LICENSE.md) License.<br>
Authored and maintained by [Kiko Beats](https://kikobeats.com) with help from [contributors](https://github.com/microlinkhq/async-ratelimiter/contributors).
> [microlink.io](https://microlink.io) · GitHub [microlink.io](https://github.com/microlinkhq) · X [@microlinkhq](https://x.com/microlinkhq)