From c2d88ffd3e7187f3c9397f13e10de839e93ad293 Mon Sep 17 00:00:00 2001 From: Hakan Ensari Date: Wed, 2 May 2012 02:17:43 +0100 Subject: [PATCH] Add HTTPClient adapter nahi/httpclient#90 --- Gemfile | 1 + lib/faraday/adapter.rb | 6 ++- lib/faraday/adapter/httpclient.rb | 80 +++++++++++++++++++++++++++++++ test/adapters/httpclient_test.rb | 10 ++++ 4 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 lib/faraday/adapter/httpclient.rb create mode 100644 test/adapters/httpclient_test.rb diff --git a/Gemfile b/Gemfile index 648da9b7..fae6612c 100644 --- a/Gemfile +++ b/Gemfile @@ -8,6 +8,7 @@ group :test do gem 'em-http-request', '~> 1.0', :require => 'em-http' gem 'em-synchrony', '~> 1.0', :require => ['em-synchrony', 'em-synchrony/em-http'], :platforms => :ruby_19 gem 'excon', '~> 0.6' + gem 'httpclient', '~> 2.2' gem 'net-http-persistent', '~> 2.5', :require => false gem 'leftright', '~> 0.9', :require => false gem 'rack-test', '~> 0.6', :require => 'rack/test' diff --git a/lib/faraday/adapter.rb b/lib/faraday/adapter.rb index 3e2f7e89..1aef8b79 100644 --- a/lib/faraday/adapter.rb +++ b/lib/faraday/adapter.rb @@ -14,7 +14,8 @@ module Faraday :Patron => 'patron', :Excon => 'excon', :Test => 'test', - :Rack => 'rack' + :Rack => 'rack', + :HTTPClient => 'httpclient' register_middleware \ :test => :Test, @@ -25,7 +26,8 @@ module Faraday :em_synchrony => :EMSynchrony, :em_http => :EMHttp, :excon => :Excon, - :rack => :Rack + :rack => :Rack, + :httpclient => :HTTPClient module Parallelism attr_writer :supports_parallel diff --git a/lib/faraday/adapter/httpclient.rb b/lib/faraday/adapter/httpclient.rb new file mode 100644 index 00000000..25ed236b --- /dev/null +++ b/lib/faraday/adapter/httpclient.rb @@ -0,0 +1,80 @@ +module Faraday + class Adapter + class HTTPClient < Faraday::Adapter + dependency 'httpclient' + + def call(env) + super + + client ||= ::HTTPClient.new + + if req = env[:request] + if proxy = req[:proxy] + configure_proxy client, proxy + end + configure_timeouts client, req + end + + if env[:url].scheme == 'https' && ssl = env[:ssl] + configure_ssl client, ssl + end + + # TODO Don't stream yet. + # https://github.com/nahi/httpclient/pull/90 + env[:body] = env[:body].read if env[:body].respond_to? :read + + resp = client.request env[:method], env[:url], + :body => env[:body], + :header => env[:request_headers] + + save_response env, resp.status, resp.body, resp.headers + + @app.call env + rescue ::HTTPClient::TimeoutError + raise Faraday::Error::TimeoutError, $! + end + + def configure_proxy(client, proxy) + client.proxy = proxy[:uri] + if proxy[:user] && proxy[:password] + client.set_proxy_auth proxy[:user], proxy[:password] + end + end + + def configure_ssl(client, ssl) + ssl_config = client.ssl_config + + ssl_config.add_trust_ca ssl[:ca_file] if ssl[:ca_file] + ssl_config.add_trust_ca ssl[:ca_path] if ssl[:ca_path] + ssl_config.cert_store = ssl[:cert_store] if ssl[:cert_store] + ssl_config.client_cert = ssl[:client_cert] if ssl[:client_cert] + ssl_config.client_key = ssl[:client_key] if ssl[:client_key] + ssl_config.verify_depth = ssl[:verify_depth] if ssl[:verify_depth] + ssl_config.verify_mode = ssl_verify_mode(ssl) + end + + def configure_timeouts(client, req) + if req[:timeout] + client.connect_timeout = req[:timeout] + client.receive_timeout = req[:timeout] + client.send_timeout = req[:timeout] + end + + if req[:open_timeout] + client.connect_timeout = req[:open_timeout] + client.send_timeout = req[:open_timeout] + end + end + + def ssl_verify_mode(ssl) + ssl[:verify_mode] || begin + if ssl.fetch(:verify, true) + OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT + else + OpenSSL::SSL::VERIFY_NONE + end + end + end + end + end +end diff --git a/test/adapters/httpclient_test.rb b/test/adapters/httpclient_test.rb new file mode 100644 index 00000000..067c5c10 --- /dev/null +++ b/test/adapters/httpclient_test.rb @@ -0,0 +1,10 @@ +require File.expand_path('../integration', __FILE__) + +module Adapters + class HttpclientTest < Faraday::TestCase + + def adapter() :httpclient end + + Integration.apply(self, :NonParallel) + end +end