2017-06-07 08:23:26 -07:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
module RateLimitHeaders
|
|
|
|
extend ActiveSupport::Concern
|
|
|
|
|
2020-03-08 07:17:39 -07:00
|
|
|
class_methods do
|
|
|
|
def override_rate_limit_headers(method_name, options = {})
|
|
|
|
around_action(only: method_name, if: :current_account) do |_controller, block|
|
2023-02-18 14:09:40 -08:00
|
|
|
block.call
|
|
|
|
ensure
|
|
|
|
rate_limiter = RateLimiter.new(current_account, options)
|
|
|
|
rate_limit_headers = rate_limiter.to_headers
|
|
|
|
response.headers.merge!(rate_limit_headers) unless response.headers['X-RateLimit-Remaining'].present? && rate_limit_headers['X-RateLimit-Remaining'].to_i > response.headers['X-RateLimit-Remaining'].to_i
|
2020-03-08 07:17:39 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-06-07 08:23:26 -07:00
|
|
|
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
|
2022-12-15 08:11:58 -08:00
|
|
|
most_limited_type, = request.env['rack.attack.throttle_data'].min_by { |_key, value| value[:limit] - value[:count] }
|
2017-12-11 06:32:29 -08:00
|
|
|
request.env['rack.attack.throttle_data'][most_limited_type]
|
2017-06-07 08:23:26 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
def request_time
|
2023-07-12 01:08:51 -07:00
|
|
|
@request_time ||= Time.now.utc
|
2017-06-07 08:23:26 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
def reset_period_offset
|
2023-02-17 19:30:23 -08:00
|
|
|
api_throttle_data[:period] - (request_time.to_i % api_throttle_data[:period])
|
2017-06-07 08:23:26 -07:00
|
|
|
end
|
|
|
|
end
|