def request uri, req = nil, &block
retried = false
bad_response = false
req = Net::HTTP::Get.new uri.request_uri unless req
@headers.each do |pair|
req.add_field(*pair)
end
@override_headers.each do |name, value|
req[name] = value
end
unless req['Connection'] then
req.add_field 'Connection', 'keep-alive'
req.add_field 'Keep-Alive', @keep_alive
end
connection = connection_for uri
connection_id = connection.object_id
begin
Thread.current[@request_key][connection_id] += 1
response = connection.request req, &block
if connection_close?(req) or
(response.http_version <= '1.0' and
not connection_keep_alive?(response)) or
connection_close?(response) then
connection.finish
end
rescue Net::HTTPBadResponse => e
message = error_message connection
finish connection
raise Error, "too many bad responses #{message}" if
bad_response or not can_retry? req
bad_response = true
retry
rescue IOError, EOFError, Timeout::Error,
Errno::ECONNABORTED, Errno::ECONNRESET, Errno::EPIPE,
Errno::EINVAL, OpenSSL::SSL::SSLError => e
if retried or not can_retry? req
due_to = "(due to #{e.message} - #{e.class})"
message = error_message connection
finish connection
raise Error, "too many connection resets #{due_to} #{message}"
end
reset connection
retried = true
retry
ensure
Thread.current[@timeout_key][connection_id] = Time.now
end
@http_versions["#{uri.host}:#{uri.port}"] ||= response.http_version
response
end