RateLimiterMiddleware.coffee 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. RateLimiter = require "../../infrastructure/RateLimiter"
  2. logger = require "logger-sharelatex"
  3. AuthenticationController = require('../Authentication/AuthenticationController')
  4. module.exports = RateLimiterMiddleware =
  5. ###
  6. Do not allow more than opts.maxRequests from a single client in
  7. opts.timeInterval. Pass an array of opts.params to segment this based on
  8. parameters in the request URL, e.g.:
  9. app.get "/project/:project_id", RateLimiterMiddleware.rateLimit(endpointName: "open-editor", params: ["project_id"])
  10. will rate limit each project_id separately.
  11. Unique clients are identified by user_id if logged in, and IP address if not.
  12. ###
  13. rateLimit: (opts) ->
  14. return (req, res, next) ->
  15. user_id = AuthenticationController.getLoggedInUserId(req) || req.ip
  16. params = (opts.params or []).map (p) -> req.params[p]
  17. params.push user_id
  18. subjectName = params.join(":")
  19. if opts.ipOnly
  20. subjectName = req.ip
  21. if !opts.endpointName?
  22. throw new Error("no endpointName provided")
  23. options = {
  24. endpointName: opts.endpointName
  25. timeInterval: opts.timeInterval or 60
  26. subjectName: subjectName
  27. throttle: opts.maxRequests or 6
  28. }
  29. RateLimiter.addCount options, (error, canContinue)->
  30. return next(error) if error?
  31. if canContinue
  32. next()
  33. else
  34. logger.warn options, "rate limit exceeded"
  35. res.status(429) # Too many requests
  36. res.write("Rate limit reached, please try again later")
  37. res.end()