Made requests object safer. Expire requests before sending error back

pull/306/head
Tim Robinson 2016-05-16 19:15:15 +00:00
rodzic 9d6c7e47d7
commit 1e04331410
1 zmienionych plików z 33 dodań i 25 usunięć

32
node_modules/c9/ratelimit.js wygenerowano vendored
Wyświetl plik

@ -7,9 +7,13 @@ var _ = require("lodash");
module.exports = ratelimit; module.exports = ratelimit;
function ratelimit(key, duration, max) { function ratelimit(key, duration, max) {
var requests = {}; var requests = Object.create(null); // in case there handles like 'constructor'
setInterval(function() { setInterval(function() {
_.forIn(requests, function (requestsForHandle, key) { Object.keys(requests).forEach(expireRequests);
}, duration * 0.75);
function expireRequests(value) {
var requestsForHandle = requests[value];
var totalToSplice = 0; var totalToSplice = 0;
var expireTime = Date.now() - duration; var expireTime = Date.now() - duration;
/* Requests are already sorted by date as they are appended, so we just loop /* Requests are already sorted by date as they are appended, so we just loop
@ -18,23 +22,27 @@ function ratelimit(key, duration, max) {
if (requestsForHandle[i] >= expireTime) break; if (requestsForHandle[i] >= expireTime) break;
totalToSplice++; totalToSplice++;
} }
requests[key].splice(0, totalToSplice); requests[value].splice(0, totalToSplice);
if (requests[key].length == 0) { if (requests[value].length == 0) {
delete requests[key]; delete requests[value];
} }
});
}, 10);
return function(req, res, next) {
var handle = req.params[key];
requests[handle] = requests[handle] || []; return true;
if (requests[handle].length >= max) { }
return function(req, res, next) {
var value = req.params[key];
requests[value] = requests[value] || [];
if (requests[value].length >= max) {
if (expireRequests(value) && requests[value].length >= max) {
var err = new error.TooManyRequests("Rate limit exceeded"); var err = new error.TooManyRequests("Rate limit exceeded");
err.retryIn = Math.min(duration, 5000); err.retryIn = Math.min(duration, 5000);
return next(err); return next(err);
} }
}
requests[handle].push(Date.now()); requests[value].push(Date.now());
return next(); return next();
}; };
} }