Express rate-limiter2
Rate limiting middleware for Express applications built on redis
Based on ded/express-limiter (https://github.com/ded/express-limiter)
npm install express-limiter2 --save
var express = require('express')
var app = express()
var client = require('redis').createClient()
var limiter = require('express-limiter2')(client, app)
limiter({
path: '/api/action',
method: 'get',
lookup: function(req) {
return [req.connection.remoteAddress];
},
total: 150,
expire: 1000 * 60 * 60
})
app.get('/api/action', function (req, res) {
res.send(200, 'ok')
})
API options
limiter(options)
path
: String
optional route path to the requestmethod
: String
optional http method. accepts get
, post
, put
, delete
, and of course Express' all
lookup
: function(req)
must return a list of string used for redis key. It can be req param, or custom data. See examples for common usages (default lookup is performed on req.path, req.method and req.connection.remoteAddress)total
: Number
allowed number of requests before getting rate limitedexpire
: Number
amount of time in ms
before the rate-limited is resetwhitelist
: function(req)
optional param allowing the ability to whitelist. return boolean
, true
to whitelist, false
to passthru to limiter.skipHeaders
: Boolean
whether to skip sending HTTP headers for rate limits ()ignoreErrors
: Boolean
whether errors generated from redis should allow the middleware to call next(). Defaults to false.keyFormatter
: function(params)
optional param to customize key generation for redis. You can specify you prefix, suffix, and the way you join key's parts (See code for default behaviour)onRateLimited
: function(req, res, next)
optional param to define the behaviour of your choice when rate limit is reached
Examples
limiter({
...
lookup: function(req) { return [req.path, req.method, req.connection.remoteAddress];}
...
})
limiter({
lookup: function(req) { return [req.path, req.method, req.headers.x-forwarded-for];}
})
limiter({
lookup: function(req) { return [req.path, req.method, req.user.id]; }
})
limiter({
path: '*',
method: 'all',
lookup: function(req) {
return [req.connection.remoteAddress, req.method, req.path];
}
})
limiter({
path: '*',
method: 'all',
lookup: function(req) {
return [req.connection.remoteAddress];
}
})
limiter({
path: '*',
method: 'all',
lookup: function(req) {
return [req.user.id, req.connection.remoteAddress];
}
})
limiter({
path: '/delete/thing',
method: 'post',
lookup: function(req) {
return [req.user.id, req.path, req.method]
},
whitelist: function (req) {
return !!req.user.is_admin
}
})
limiter({
path: '/delete/thing',
method: 'post',
lookup: function(req) {
return [req.user.id, req.path, req.method]
},
whitelist: function (req) {
return !!req.user.is_admin
},
skipHeaders: true
})
limiter({
path: '/api/*',
method: 'all',
lookup: function(req) {
return [req.user.id, req.connection.remoteAddress, 'api'];
}
})
limiter({
path: '/api/*',
method: 'get',
lookup: function(req) {
return [req.user.id, req.path, req.method]
},
keyFormatter: function(params) {
return 'myRateLimit:' + params.join("-");
},
whitelist: function (req) {
return !!req.user.is_admin
}
})
limiter({
path: '*',
method: 'all',
lookup: function(req) {
return [req.user.id, req.connection.remoteAddress];
},
onRateLimited: function(req, res, next) {
return next({error: {status: 429, message: 'too many requests'}});
}
})
as direct middleware
var limiter = require('express-limiter')(client)
app.post('/user/update', limiter({ lookup: function(req) { return [req.user.id, req.path, req.method]} }), function (req, res) {
User.find(req.user.id).update(function (err) {
if (err) next(err)
else res.send('ok')
})
})
app.get('/api/*', limiter({
lookup: function(req) {
return [req.user.id, 'api'];
}
}), function (req, res) {
User.find(req.user.id).update(function (err) {
if (err) next(err)
else res.send('ok')
})
})
License MIT
Happy Rate Limiting!