lib/httpx/plugins/retries.rb in httpx-0.22.5 vs lib/httpx/plugins/retries.rb in httpx-0.23.0

- old
+ new

@@ -9,11 +9,11 @@ # module Retries MAX_RETRIES = 3 # TODO: pass max_retries in a configure/load block - IDEMPOTENT_METHODS = %i[get options head put delete].freeze + IDEMPOTENT_METHODS = %w[GET OPTIONS HEAD PUT DELETE].freeze RETRYABLE_ERRORS = [ IOError, EOFError, Errno::ECONNRESET, Errno::ECONNABORTED, @@ -94,11 +94,11 @@ ( response.is_a?(ErrorResponse) && __retryable_error?(response.error) ) # rubocop:enable Style/MultilineTernaryOperator ) - response.close if response.respond_to?(:close) + __try_partial_retry(request, response) log { "failed to get response, #{request.retries} tries to go..." } request.retries -= 1 request.transition(:idle) retry_after = options.retry_after @@ -132,17 +132,64 @@ end def __retryable_error?(ex) RETRYABLE_ERRORS.any? { |klass| ex.is_a?(klass) } end + + # + # Atttempt to set the request to perform a partial range request. + # This happens if the peer server accepts byte-range requests, and + # the last response contains some body payload. + # + def __try_partial_retry(request, response) + response = response.response if response.is_a?(ErrorResponse) + + return unless response + + unless response.headers.key?("accept-ranges") && + response.headers["accept-ranges"] == "bytes" && # there's nothing else supported though... + (original_body = response.body) + response.close if response.respond_to?(:close) + return + end + + request.partial_response = response + + size = original_body.bytesize + + request.headers["range"] = "bytes=#{size}-" + end end module RequestMethods attr_accessor :retries + attr_writer :partial_response + def initialize(*args) super @retries = @options.max_retries + end + + def response=(response) + if @partial_response + if response.is_a?(Response) && response.status == 206 + response.from_partial_response(@partial_response) + else + @partial_response.close + end + @partial_response = nil + end + + super + end + end + + module ResponseMethods + def from_partial_response(response) + @status = response.status + @headers = response.headers + @body = response.body end end end register_plugin :retries, Retries end