- # frozen_string_literal: true
-
- module RateLimitHeaders
- extend ActiveSupport::Concern
-
- included do
- before_action :set_rate_limit_headers, if: :rate_limited_request?
- end
-
- private
-
- def set_rate_limit_headers
- apply_header_limit
- apply_header_remaining
- apply_header_reset
- end
-
- def rate_limited_request?
- !request.env['rack.attack.throttle_data'].nil?
- end
-
- def apply_header_limit
- response.headers['X-RateLimit-Limit'] = rate_limit_limit
- end
-
- def rate_limit_limit
- api_throttle_data[:limit].to_s
- end
-
- def apply_header_remaining
- response.headers['X-RateLimit-Remaining'] = rate_limit_remaining
- end
-
- def rate_limit_remaining
- (api_throttle_data[:limit] - api_throttle_data[:count]).to_s
- end
-
- def apply_header_reset
- response.headers['X-RateLimit-Reset'] = rate_limit_reset
- end
-
- def rate_limit_reset
- (request_time + reset_period_offset).iso8601(6)
- end
-
- def api_throttle_data
- most_limited_type, = request.env['rack.attack.throttle_data'].min_by { |_, v| v[:limit] }
- request.env['rack.attack.throttle_data'][most_limited_type]
- end
-
- def request_time
- @_request_time ||= Time.now.utc
- end
-
- def reset_period_offset
- api_throttle_data[:period] - request_time.to_i % api_throttle_data[:period]
- end
- end
|