RateLimiterMiddlewear.coffee 1.3 KB

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