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