apiLimitsMiddleware.js 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. var config = require('../../../server_config/settings.json');
  2. var debug = require('debug')('apiLimitsMiddleware');
  3. var apiLimitsMiddleware = function(req, res, next) {
  4. 'use strict';
  5. debug('Entering API Limits Middleware with IP address %s', req.connection.remoteAddress);
  6. if (req.path.indexOf('/api/') === 0 && !res.locals.hasApiKey) {
  7. if (req.path === '/api/runs') {
  8. if (!runsTable.accepts(req.connection.remoteAddress)) {
  9. // Sorry :/
  10. debug('Too many tests launched from IP address %s', req.connection.remoteAddress);
  11. res.status(429).send('Too Many Requests');
  12. return;
  13. }
  14. }
  15. if (!callsTable.accepts(req.connection.remoteAddress)) {
  16. // Sorry :/
  17. debug('Too many API requests from IP address %s', req.connection.remoteAddress);
  18. res.status(429).send('Too Many Requests');
  19. return;
  20. }
  21. debug('Not blocked by the API limits');
  22. // It's ok for the moment
  23. }
  24. next();
  25. };
  26. var RecordTable = function(maxPerDay) {
  27. var table = {};
  28. // Check if the user overpassed the limit and save its visit
  29. this.accepts = function(ipAddress) {
  30. if (table[ipAddress]) {
  31. this.cleanEntry(ipAddress);
  32. debug('%d visits in the last 24 hours', table[ipAddress].length);
  33. if (table[ipAddress].length >= maxPerDay) {
  34. return false;
  35. } else {
  36. table[ipAddress].push(Date.now());
  37. }
  38. } else {
  39. table[ipAddress] = [];
  40. table[ipAddress].push(Date.now());
  41. }
  42. return true;
  43. };
  44. // Clean the table for this guy
  45. this.cleanEntry = function(ipAddress) {
  46. table[ipAddress] = table[ipAddress].filter(function(date) {
  47. return date > Date.now() - 1000*60*60*24;
  48. });
  49. };
  50. // Clean the entire table once in a while
  51. this.removeOld = function() {
  52. for (var ipAddress in table) {
  53. this.cleanEntry(ipAddress);
  54. }
  55. };
  56. };
  57. // Init the records tables
  58. var runsTable = new RecordTable(config.maxAnonymousRunsPerDay);
  59. var callsTable = new RecordTable(config.maxAnonymousCallsPerDay);
  60. module.exports = apiLimitsMiddleware;