rate_limit_headers.rb 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. # frozen_string_literal: true
  2. module RateLimitHeaders
  3. extend ActiveSupport::Concern
  4. included do
  5. before_action :set_rate_limit_headers, if: :rate_limited_request?
  6. end
  7. private
  8. def set_rate_limit_headers
  9. apply_header_limit
  10. apply_header_remaining
  11. apply_header_reset
  12. end
  13. def rate_limited_request?
  14. !request.env['rack.attack.throttle_data'].nil?
  15. end
  16. def apply_header_limit
  17. response.headers['X-RateLimit-Limit'] = rate_limit_limit
  18. end
  19. def rate_limit_limit
  20. api_throttle_data[:limit].to_s
  21. end
  22. def apply_header_remaining
  23. response.headers['X-RateLimit-Remaining'] = rate_limit_remaining
  24. end
  25. def rate_limit_remaining
  26. (api_throttle_data[:limit] - api_throttle_data[:count]).to_s
  27. end
  28. def apply_header_reset
  29. response.headers['X-RateLimit-Reset'] = rate_limit_reset
  30. end
  31. def rate_limit_reset
  32. (request_time + reset_period_offset).iso8601(6)
  33. end
  34. def api_throttle_data
  35. most_limited_type, = request.env['rack.attack.throttle_data'].min_by { |_, v| v[:limit] }
  36. request.env['rack.attack.throttle_data'][most_limited_type]
  37. end
  38. def request_time
  39. @_request_time ||= Time.now.utc
  40. end
  41. def reset_period_offset
  42. api_throttle_data[:period] - request_time.to_i % api_throttle_data[:period]
  43. end
  44. end