node-redis-rate-limiter/README.md

188 lines
4.4 KiB
Markdown
Raw Normal View History

# redis-rate-limiter
2014-08-21 02:20:59 -04:00
2014-10-03 01:51:12 -04:00
[![NPM](http://img.shields.io/npm/v/redis-rate-limiter.svg?style=flat)](https://npmjs.org/package/redis-rate-limiter)
[![License](http://img.shields.io/npm/l/redis-rate-limiter.svg?style=flat)](https://github.com/TabDigital/redis-rate-limiter)
[![Build Status](http://img.shields.io/travis/TabDigital/redis-rate-limiter.svg?style=flat)](http://travis-ci.org/TabDigital/redis-rate-limiter)
[![Dependencies](http://img.shields.io/david/TabDigital/redis-rate-limiter.svg?style=flat)](https://david-dm.org/TabDigital/redis-rate-limiter)
[![Dev dependencies](http://img.shields.io/david/dev/TabDigital/redis-rate-limiter.svg?style=flat)](https://david-dm.org/TabDigital/redis-rate-limiter)
[![Known Vulnerabilities](https://snyk.io/package/npm/redis-rate-limiter/badge.svg)](https://snyk.io/package/npm/redis-rate-limiter)
2014-10-03 01:51:12 -04:00
Rate-limit any operation, backed by Redis.
2014-08-21 02:20:59 -04:00
- Inspired by [ratelimiter](https://www.npmjs.org/package/ratelimiter)
- But uses a fixed-window algorithm
- Great performance (>10000 checks/sec on local redis)
- No race conditions
2014-08-21 02:20:59 -04:00
Very easy to plug into `Express` or `Restify` to rate limit your `Node.js` API.
2014-08-21 02:20:59 -04:00
## Usage
2014-08-21 02:20:59 -04:00
Step 1: create a Redis connection
2014-08-21 02:20:59 -04:00
```js
var redis = require('redis');
var client = redis.createClient(6379, 'localhost', {enable_offline_queue: false});
2014-08-21 02:20:59 -04:00
```
Step 2: create your rate limiter
2014-08-21 02:20:59 -04:00
```js
var rateLimiter = require('redis-rate-limiter');
var limit = rateLimiter.create({
redis: client,
key: function(x) { return x.id },
rate: '100/minute'
});
```
2014-08-21 02:20:59 -04:00
And go
```js
limit(request, function(err, rate) {
if (err) {
console.warn('Rate limiting not available');
} else {
console.log('Rate window: ' + rate.window); // 60
console.log('Rate limit: ' + rate.limit); // 100
console.log('Rate current: ' + rate.current); // 74
if (rate.over) {
console.error('Over the limit!');
}
}
});
2014-08-21 02:20:59 -04:00
```
## Options
2014-08-21 02:20:59 -04:00
### `redis`
2014-08-21 02:20:59 -04:00
A pre-created Redis client.
Make sure offline queueing is disabled.
2014-08-21 02:20:59 -04:00
```js
var client = redis.createClient(6379, 'localhost', {
enable_offline_queue: false
});
2014-08-21 02:20:59 -04:00
```
### `key`
2014-08-21 02:20:59 -04:00
The key is how requests are grouped for rate-limiting.
Typically, this would be a user ID, a type of operation...
2014-08-21 02:20:59 -04:00
There are several helpers built-in:
```js
// identify users by IP
2014-08-21 02:20:59 -04:00
key: 'ip'
// identify users by their IP network (255.255.255.0 mask)
2014-08-21 02:20:59 -04:00
key: 'ip/32'
// identify users by the X-Forwarded-For header
// careful: this is just an HTTP header and can easily be spoofed
2014-08-21 02:20:59 -04:00
key: 'x-forwarded-for'
```
You can also specify any custom function:
```js
// rate-limit each user separately
key: function(x) { return x.user.id; }
2014-08-21 02:20:59 -04:00
// rate limit per user and operation type
key: function(x) { return x.user.id + ':' + x.operation; }
// rate limit everyone in the same bucket
key: function(x) { return 'single-bucket'; }
2014-08-21 02:20:59 -04:00
```
### `window`
This is the duration over which rate-limiting is applied, in seconds.
2014-08-21 02:20:59 -04:00
```js
// rate limit per minute
window: 60
2014-08-21 02:20:59 -04:00
// rate limit per hour
window: 3600
2014-08-21 02:20:59 -04:00
```
Note that this is **not a rolling window**.
If you specify `10 requests / minute`, a user would be able
to execute 10 requests at `00:59` and another 10 at `01:01`.
Then they won't be able to make another request until `02:00`.
### `limit`
2014-08-21 02:20:59 -04:00
This is the total number of requests a unique `key` can make during the `window`.
```js
limit: 100
2014-08-21 02:20:59 -04:00
```
### `rate`
Rate is a shorthand notation to combine `limit` and `window`.
2014-08-21 02:20:59 -04:00
```js
rate: '10/second'
rate: '100/minute'
rate: '1000/hour'
```
2014-08-21 02:20:59 -04:00
Or the even shorter
2014-08-21 02:20:59 -04:00
```js
rate: '10/s'
rate: '100/m'
rate: '100/h'
2014-08-21 02:20:59 -04:00
```
*Note:* the rate is parsed ahead of time, so this notation doesn't affect performance.
## HTTP middleware
This package contains a pre-built middleware,
which takes the same options
2014-08-21 02:20:59 -04:00
```js
var rateLimiter = require('redis-rate-limiter');
var middleware = rateLimiter.middleware({
redis: client,
key: 'ip',
rate: '100/minute'
});
server.use(middleware);
2014-08-21 02:20:59 -04:00
```
It rejects any rate-limited requests with a status code of `HTTP 429`,
and an empty body.
*Note:* if you want to rate limit several routes individually, don't forget to use the route name as part of the `key`, for example using Restify:
```js
function ipAndRoute(req) {
return req.connection.remoteAddress + ':' + req.route.name;
}
server.get(
{name: 'routeA', path: '/a'},
rateLimiter.middleware({redis: client, key: ipAndRoute, rate: '10/minute'}),
controllerA
);
server.get(
{name: 'routeB', path: '/b'},
rateLimiter.middleware({redis: client, key: ipAndRoute, rate: '20/minute'}),
controllerB
);
```