node-redis-rate-limiter/lib/index.js

53 lines
1.5 KiB
JavaScript
Raw Normal View History

2014-08-21 02:20:59 -04:00
var redis = require('redis');
var util = require('util');
var url = require('url');
var EventEmitter = require('events').EventEmitter;
var options = require('./options');
function RateLimiter(config) {
var cnx = url.parse(config.redis);
this.client = redis.createClient(cnx.port, cnx.hostname, {enable_offline_queue: false});
this.client.on('error', this.emit.bind(this, 'unavailable'));
}
util.inherits(RateLimiter, EventEmitter);
module.exports = RateLimiter;
RateLimiter.prototype.middleware = function(opts) {
var self = this;
opts = options.canonical(opts);
return function(req, res, next) {
var key = opts.key(req);
var tempKey = 'ratelimittemp:' + key;
var realKey = 'ratelimit:' + key;
self.client
.multi()
.setex(tempKey, opts.window, 0)
.renamenx(tempKey, realKey)
.incr(realKey)
.exec(function(err, results) {
if(err) {
self.emit('unavailable', err);
next();
} else {
var rate = {
current: results[2],
limit: opts.limit,
window: opts.window
};
if (rate.current <= rate.limit) {
self.emit('accepted', rate, req, res, next);
next();
} else {
if (self.listeners('rejected').length === 0) {
res.writeHead(429);
res.end();
} else {
self.emit('rejected', rate, req, res, next);
}
}
}
});
};
};