require 'net/http' module Seahorse module Client # @api private module NetHttp # @api private module Patches def self.apply! return unless RUBY_VERSION < '2.5' if RUBY_VERSION >= '2.3' Net::HTTP::IDEMPOTENT_METHODS_.clear return end # no further patches needed for above versions if RUBY_VERSION >= '2.0' Net::HTTP.send(:include, Ruby_2) Net::HTTP::IDEMPOTENT_METHODS_.clear elsif RUBY_VERSION >= '1.9.3' Net::HTTP.send(:include, Ruby_1_9_3) end Net::HTTP.send(:alias_method, :old_transport_request, :transport_request) Net::HTTP.send(:alias_method, :transport_request, :new_transport_request) end module Ruby_2 def new_transport_request(req) count = 0 begin begin_transport req res = catch(:response) { req.exec @socket, @curr_http_version, edit_path(req.path) begin res = Net::HTTPResponse.read_new(@socket) res.decode_content = req.decode_content end while res.kind_of?(Net::HTTPInformation) res.uri = req.uri res } res.reading_body(@socket, req.response_body_permitted?) { yield res if block_given? } rescue Net::OpenTimeout raise rescue Net::ReadTimeout, IOError, EOFError, Errno::ECONNRESET, Errno::ECONNABORTED, Errno::EPIPE, # avoid a dependency on OpenSSL defined?(OpenSSL::SSL) ? OpenSSL::SSL::SSLError : IOError, Timeout::Error => exception if count == 0 && Net::HTTP::IDEMPOTENT_METHODS_.include?(req.method) count += 1 @socket.close if @socket and not @socket.closed? D "Conn close because of error #{exception}, and retry" if req.body_stream if req.body_stream.respond_to?(:rewind) req.body_stream.rewind else raise end end retry end D "Conn close because of error #{exception}" @socket.close if @socket and not @socket.closed? raise end end_transport req, res res rescue => exception D "Conn close because of error #{exception}" @socket.close if @socket and not @socket.closed? raise exception end end module Ruby_1_9_3 def new_transport_request(req) begin_transport req res = catch(:response) { req.exec @socket, @curr_http_version, edit_path(req.path) begin res = Net::HTTPResponse.read_new(@socket) end while res.kind_of?(Net::HTTPContinue) res } res.reading_body(@socket, req.response_body_permitted?) { yield res if block_given? } end_transport req, res res rescue => exception D "Conn close because of error #{exception}" @socket.close if @socket and not @socket.closed? raise exception end end end end end end