apiLimitsMiddleware.js 2.4 KB

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