refactor NetHttp and NetHttpPersistent adapters

closes #133
This commit is contained in:
Mislav Marohnić 2012-04-15 15:42:31 +02:00
parent a019a11946
commit e8118055d5
3 changed files with 86 additions and 115 deletions

View File

@ -22,60 +22,17 @@ module Faraday
NET_HTTP_EXCEPTIONS << OpenSSL::SSL::SSLError if defined?(OpenSSL)
def call(env)
super
url = env[:url]
http = net_http_connection(env)
configure_ssl(http, env[:ssl]) if env[:url].scheme == 'https' and env[:ssl]
req = env[:request]
http = net_http_class(env).new(url.host, url.port)
if http.use_ssl = (url.scheme == 'https' && (ssl = env[:ssl]) && true)
http.verify_mode = ssl[:verify_mode] || begin
if ssl.fetch(:verify, true)
# Use the default cert store by default, i.e. system ca certs
store = OpenSSL::X509::Store.new
store.set_default_paths
http.cert_store = store
OpenSSL::SSL::VERIFY_PEER
else
OpenSSL::SSL::VERIFY_NONE
end
end
http.cert = ssl[:client_cert] if ssl[:client_cert]
http.key = ssl[:client_key] if ssl[:client_key]
http.ca_file = ssl[:ca_file] if ssl[:ca_file]
http.ca_path = ssl[:ca_path] if ssl[:ca_path]
http.cert_store = ssl[:cert_store] if ssl[:cert_store]
http.verify_depth = ssl[:verify_depth] if ssl[:verify_depth]
http.ssl_version = ssl[:version] if ssl[:version]
end
http.read_timeout = http.open_timeout = req[:timeout] if req[:timeout]
http.open_timeout = req[:open_timeout] if req[:open_timeout]
if :get != env[:method] or env[:body]
http_request = Net::HTTPGenericRequest.new \
env[:method].to_s.upcase, # request method
!!env[:body], # is there request body
:head != env[:method], # is there response body
url.request_uri, # request uri path
env[:request_headers] # request headers
if env[:body].respond_to?(:read)
http_request.body_stream = env[:body]
env[:body] = nil
end
end
begin
http_response = if :get == env[:method] and env[:body].nil?
# prefer `get` to `request` because the former handles gzip (ruby 1.9)
http.get url.request_uri, env[:request_headers]
else
http.request http_request, env[:body]
end
http_response = perform_request(http, env)
rescue *NET_HTTP_EXCEPTIONS
raise Error::ConnectionFailed, $!
end
@ -91,11 +48,63 @@ module Faraday
raise Faraday::Error::TimeoutError, err
end
def net_http_class(env)
def create_request(env)
request = Net::HTTPGenericRequest.new \
env[:method].to_s.upcase, # request method
!!env[:body], # is there request body
:head != env[:method], # is there response body
env[:url].request_uri, # request uri path
env[:request_headers] # request headers
if env[:body].respond_to?(:read)
request.body_stream = env[:body]
else
request.body = env[:body]
end
request
end
def perform_request(http, env)
if :get == env[:method] and !env[:body]
# prefer `get` to `request` because the former handles gzip (ruby 1.9)
http.get env[:url].request_uri, env[:request_headers]
else
http.request create_request(env)
end
end
def net_http_connection(env)
if proxy = env[:request][:proxy]
Net::HTTP::Proxy(proxy[:uri].host, proxy[:uri].port, proxy[:user], proxy[:password])
else
Net::HTTP
end.new(env[:url].host, env[:url].port)
end
def configure_ssl(http, ssl)
http.use_ssl = true
http.verify_mode = ssl_verify_mode(ssl)
http.cert = ssl[:client_cert] if ssl[:client_cert]
http.key = ssl[:client_key] if ssl[:client_key]
http.ca_file = ssl[:ca_file] if ssl[:ca_file]
http.ca_path = ssl[:ca_path] if ssl[:ca_path]
http.cert_store = ssl[:cert_store] if ssl[:cert_store]
http.verify_depth = ssl[:verify_depth] if ssl[:verify_depth]
http.ssl_version = ssl[:version] if ssl[:version]
end
def ssl_verify_mode(ssl)
ssl[:verify_mode] || begin
if ssl.fetch(:verify, true)
# Use the default cert store by default, i.e. system ca certs
store = OpenSSL::X509::Store.new
store.set_default_paths
http.cert_store = store
OpenSSL::SSL::VERIFY_PEER
else
OpenSSL::SSL::VERIFY_NONE
end
end
end
end

View File

@ -1,72 +1,37 @@
require 'faraday/adapter/net_http'
module Faraday
class Adapter
class NetHttpPersistent < Faraday::Adapter
# Experimental adapter for net-http-persistent
class NetHttpPersistent < NetHttp
dependency 'net/http/persistent'
def call(env)
super
url = env[:url]
req = env[:request]
http = Net::HTTP::Persistent.new("#{url.host}:#{url.port}", env[:request][:proxy])
if url.scheme == 'https' && (ssl = env[:ssl]) && true
http.verify_mode = ssl[:verify_mode] || begin
if ssl.fetch(:verify, true)
# Use the default cert store by default, i.e. system ca certs
store = OpenSSL::X509::Store.new
store.set_default_paths
http.cert_store = store
OpenSSL::SSL::VERIFY_PEER
else
OpenSSL::SSL::VERIFY_NONE
end
end
http.ssl_version = ssl[:version] if ssl[:version]
http.certificate = ssl[:client_cert] if ssl[:client_cert]
http.private_key = ssl[:client_key] if ssl[:client_key]
http.ca_file = ssl[:ca_file] if ssl[:ca_file]
http.cert_store = ssl[:cert_store] if ssl[:cert_store]
end
http.read_timeout = http.open_timeout = req[:timeout] if req[:timeout]
http.open_timeout = req[:open_timeout] if req[:open_timeout]
if :get != env[:method] || env[:body]
http_request = Net::HTTPGenericRequest.new \
env[:method].to_s.upcase, # request method
!!env[:body], # is there request body
:head != env[:method], # is there response body
url.request_uri, # request uri path
env[:request_headers] # request headers
if env[:body].respond_to?(:read)
http_request.body_stream = env[:body]
env[:body] = nil
elsif env[:body]
http_request.body = env[:body]
end
end
begin
http_response = http.request url, http_request
rescue Errno::ECONNREFUSED
raise Error::ConnectionFailed, $!
end
save_response(env, http_response.code.to_i, http_response.body) do |response_headers|
http_response.each_header do |key, value|
response_headers[key] = value
end
end
@app.call env
rescue Errno::ETIMEDOUT => e1
raise Faraday::Error::TimeoutError, e1
rescue Net::HTTP::Persistent::Error => e2
raise Faraday::Error::TimeoutError, e2 if e2.message.include?("Timeout::Error")
# TODO: investigate is it safe to create a new Persistent instance for
# every request, or does it defy the purpose of persistent connections
def net_http_connection(env)
Net::HTTP::Persistent.new 'Faraday',
env[:request][:proxy] ? env[:request][:proxy][:uri] : nil
end
def perform_request(http, env)
http.request env[:url], create_request(env)
rescue Net::HTTP::Persistent::Error => error
if error.message.include? 'Timeout::Error'
raise Faraday::Error::TimeoutError, error
else
raise
end
end
def configure_ssl(http, ssl)
http.verify_mode = ssl_verify_mode(ssl)
http.certificate = ssl[:client_cert] if ssl[:client_cert]
http.private_key = ssl[:client_key] if ssl[:client_key]
http.ca_file = ssl[:ca_file] if ssl[:ca_file]
http.cert_store = ssl[:cert_store] if ssl[:cert_store]
http.ssl_version = ssl[:version] if ssl[:version]
end
end
end
end

View File

@ -5,10 +5,7 @@ module Adapters
def adapter() :net_http_persistent end
behaviors = [:NonParallel]
behaviors << :Compression if RUBY_VERSION >= '1.9'
Integration.apply(self, *behaviors)
Integration.apply(self, :NonParallel)
end
end