1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
|
# frozen_string_literal: true
module HTTPX
module Plugins
#
# This plugin adds support for retrying requests when the request:
#
# * is rate limited;
# * when the server is unavailable (503);
# * when a 3xx request comes with a "retry-after" value
#
# https://gitlab.com/os85/httpx/wikis/Rate-Limiter
#
module RateLimiter
RATE_LIMIT_CODES = [429, 503].freeze
class << self
def load_dependencies(klass)
klass.plugin(:retries, retry_after: method(:retry_after_rate_limit))
end
# Servers send the "Retry-After" header field to indicate how long the
# user agent ought to wait before making a follow-up request. When
# sent with a 503 (Service Unavailable) response, Retry-After indicates
# how long the service is expected to be unavailable to the client.
# When sent with any 3xx (Redirection) response, Retry-After indicates
# the minimum time that the user agent is asked to wait before issuing
# the redirected request.
#
def retry_after_rate_limit(_, response)
return unless response.is_a?(Response)
retry_after = response.headers["retry-after"]
return unless retry_after
Utils.parse_retry_after(retry_after)
end
end
module InstanceMethods
private
def retryable_request?(request, response, options)
super || rate_limit_error?(response)
end
def retryable_response?(response, options)
rate_limit_error?(response) || super
end
def rate_limit_error?(response)
response.is_a?(Response) && RATE_LIMIT_CODES.include?(response.status)
end
end
end
register_plugin :rate_limiter, RateLimiter
end
end
|