2014-08-21 02:20:59 -04:00
|
|
|
var assert = require('assert');
|
|
|
|
var moment = require('moment');
|
|
|
|
var ip = require('ip');
|
|
|
|
|
|
|
|
exports.canonical = function(opts) {
|
|
|
|
|
|
|
|
var canon = {};
|
|
|
|
|
2014-08-21 23:51:33 -04:00
|
|
|
// Redis connection
|
|
|
|
assert.equal(typeof opts.redis, 'object', 'Invalid redis client');
|
|
|
|
canon.redis = opts.redis;
|
|
|
|
|
2014-08-21 02:20:59 -04:00
|
|
|
// Key function
|
|
|
|
if (typeof opts.key === 'function') canon.key = opts.key;
|
|
|
|
if (typeof opts.key === 'string') canon.key = keyShorthands[opts.key];
|
|
|
|
|
|
|
|
// Rate shorthand
|
|
|
|
if (opts.rate) {
|
|
|
|
assert.equal(typeof opts.rate, 'string', 'Invalid rate: ' + opts.rate);
|
2014-08-21 23:51:33 -04:00
|
|
|
var match = opts.rate.match(/^(\d+)\s*\/\s*([a-z]+)$/);
|
2014-08-21 02:20:59 -04:00
|
|
|
assert.ok(match, 'Invalid rate: ' + opts.rate);
|
|
|
|
canon.limit = parseInt(match[1], 10);
|
|
|
|
canon.window = moment.duration(1, match[2]) / 1000;
|
2014-08-22 01:50:49 -04:00
|
|
|
assert.notEqual(canon.limit, 0, 'Invalid rate limit: ' + opts.rate);
|
|
|
|
assert.notEqual(canon.window, 0, 'Invalid rate window: ' + opts.rate);
|
2014-08-21 02:20:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Limit + window
|
|
|
|
if (opts.limit) canon.limit = opts.limit;
|
|
|
|
if (opts.window) canon.window = opts.window;
|
|
|
|
|
|
|
|
// Check option types
|
|
|
|
assert.equal(typeof canon.key, 'function', 'Invalid key: ' + opts.key);
|
|
|
|
assert.equal(typeof canon.limit, 'number', 'Invalid limit: ' + canon.limit);
|
|
|
|
assert.equal(typeof canon.window, 'number', 'Invalid window: ' + canon.window);
|
|
|
|
|
|
|
|
return canon;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
var keyShorthands = {
|
|
|
|
'ip': function(req) {
|
|
|
|
return req.connection.remoteAddress;
|
|
|
|
},
|
|
|
|
'ip/32': function (req) {
|
|
|
|
return ip.mask(req.connection.remoteAddress, '255.255.255.0') + '/32';
|
|
|
|
}
|
|
|
|
};
|