Support adapter customization (#651)

* add initializer on Faraday::Adapter that accept and store a block with custom configuration
use the `@ config_block ` block on `net_http` and `net_http_persistent` adapters
added tests

* fixes warning in tests
patron was supporting custom block already! Small refactoring to conform to other adapters

* added implementation for httpclient
excon and EM adapters now all support `connection_options` in the initializer

* additional test for httpclient adapter
This commit is contained in:
Mattia 2017-01-13 12:07:01 +00:00 committed by GitHub
parent f58f251051
commit f994b054f9
15 changed files with 117 additions and 21 deletions

View File

@ -30,6 +30,12 @@ module Faraday
extend Parallelism
self.supports_parallel = false
def initialize(app = nil, opts = {}, &block)
super(app)
@connection_options = opts
@config_block = block
end
def call(env)
env.clear_body if env.needs_body?
end

View File

@ -138,7 +138,7 @@ module Faraday
# TODO: reuse the connection to support pipelining
def perform_single_request(env)
req = EventMachine::HttpRequest.new(env[:url], connection_config(env))
req = create_request(env)
req.setup_request(env[:method], request_config(env)).callback { |client|
status = client.response_header.status
reason = client.response_header.http_reason
@ -150,6 +150,10 @@ module Faraday
}
end
def create_request(env)
EventMachine::HttpRequest.new(env[:url], connection_config(env).merge(@connection_options))
end
def error_message(client)
client.error or "request failed"
end

View File

@ -19,7 +19,7 @@ module Faraday
def call(env)
super
request = EventMachine::HttpRequest.new(Utils::URI(env[:url].to_s), connection_config(env))
request = create_request(env)
http_method = env[:method].to_s.downcase.to_sym
@ -87,6 +87,10 @@ module Faraday
raise
end
end
def create_request(env)
EventMachine::HttpRequest.new(Utils::URI(env[:url].to_s), connection_config(env).merge(@connection_options))
end
end
end
end

View File

@ -3,11 +3,6 @@ module Faraday
class Excon < Faraday::Adapter
dependency 'excon'
def initialize(app, connection_options = {})
@connection_options = connection_options
super(app)
end
def call(env)
super
@ -50,7 +45,7 @@ module Faraday
end
end
conn = ::Excon.new(env[:url].to_s, opts.merge(@connection_options))
conn = create_connection(env, opts)
resp = conn.request \
:method => env[:method].to_s.upcase,
@ -72,6 +67,10 @@ module Faraday
raise Error::TimeoutError, err
end
def create_connection(env, opts)
::Excon.new(env[:url].to_s, opts.merge(@connection_options))
end
# TODO: support streaming requests
def read_body(env)
env[:body].respond_to?(:read) ? env[:body].read : env[:body]

View File

@ -29,6 +29,8 @@ module Faraday
configure_ssl ssl
end
configure_client
# TODO Don't stream yet.
# https://github.com/nahi/httpclient/pull/90
env[:body] = env[:body].read if env[:body].respond_to? :read
@ -95,6 +97,10 @@ module Faraday
end
end
def configure_client
@config_block.call(client) if @config_block
end
def ssl_cert_store(ssl)
return ssl[:cert_store] if ssl[:cert_store]
# Memoize the cert store so that the same one is passed to

View File

@ -32,10 +32,7 @@ module Faraday
super
with_net_http_connection(env) do |http|
configure_ssl(http, env[:ssl]) if env[:url].scheme == 'https' and env[:ssl]
req = env[:request]
http.read_timeout = http.open_timeout = req[:timeout] if req[:timeout]
http.open_timeout = req[:open_timeout] if req[:open_timeout]
configure_request(http, env[:request])
begin
http_response = perform_request(http, env)
@ -109,6 +106,13 @@ module Faraday
http.ssl_version = ssl[:version] if ssl[:version]
end
def configure_request(http, req)
http.read_timeout = http.open_timeout = req[:timeout] if req[:timeout]
http.open_timeout = req[:open_timeout] if req[:open_timeout]
@config_block.call(http) if @config_block
end
def ssl_cert_store(ssl)
return ssl[:cert_store] if ssl[:cert_store]
# Use the default cert store by default, i.e. system ca certs

View File

@ -7,8 +7,8 @@ module Faraday
class NetHttpPersistent < NetHttp
dependency 'net/http/persistent'
def with_net_http_connection(env)
if proxy = env[:request][:proxy]
def net_http_connection(env)
if (proxy = env[:request][:proxy])
proxy_uri = ::URI::HTTP === proxy[:uri] ? proxy[:uri].dup : ::URI.parse(proxy[:uri].to_s)
proxy_uri.user = proxy_uri.password = nil
# awful patch for net-http-persistent 2.8 not unescaping user/password
@ -16,9 +16,10 @@ module Faraday
define_method(:user) { proxy[:user] }
define_method(:password) { proxy[:password] }
end if proxy[:user]
return Net::HTTP::Persistent.new 'Faraday', proxy_uri
end
yield Net::HTTP::Persistent.new 'Faraday', proxy_uri
Net::HTTP::Persistent.new 'Faraday'
end
def perform_request(http, env)

View File

@ -3,11 +3,6 @@ module Faraday
class Patron < Faraday::Adapter
dependency 'patron'
def initialize(app, &block)
super(app)
@block = block
end
def call(env)
super
@ -73,7 +68,7 @@ module Faraday
def create_session
session = ::Patron::Session.new
session.insecure = true
@block.call(session) if @block
@config_block.call(session) if @config_block
session
end
end

View File

@ -16,5 +16,15 @@ module Adapters
end
end unless jruby? and ssl_mode?
# https://github.com/eventmachine/eventmachine/issues/180
def test_custom_adapter_config
url = URI('https://example.com:1234')
adapter = Faraday::Adapter::EMHttp.new nil, inactivity_timeout: 20
req = adapter.create_request(url: url, request: {})
assert_equal 20, req.connopts.inactivity_timeout
end
end
end

View File

@ -18,5 +18,15 @@ module Adapters
end
end
end
def test_custom_adapter_config
url = URI('https://example.com:1234')
adapter = Faraday::Adapter::EMSynchrony.new nil, inactivity_timeout: 20
req = adapter.create_request(url: url, request: {})
assert_equal 20, req.connopts.inactivity_timeout
end
end
end

View File

@ -16,5 +16,15 @@ module Adapters
# https://github.com/geemus/excon/issues/358
undef :test_connection_error if RUBY_VERSION >= '2.1.0'
end
def test_custom_adapter_config
url = URI('https://example.com:1234')
adapter = Faraday::Adapter::Excon.new nil, debug_request: true
conn = adapter.create_connection({url: url}, {})
assert_equal true, conn.data[:debug_request]
end
end
end

View File

@ -16,6 +16,19 @@ module Adapters
conn = create_connection :request => { :bind => { :host => host } }
assert_equal host, conn.options[:bind][:host]
end
def test_custom_adapter_config
adapter = Faraday::Adapter::HTTPClient.new do |client|
client.keep_alive_timeout = 20
client.ssl_config.timeout = 25
end
client = adapter.client
adapter.configure_client
assert_equal 20, client.keep_alive_timeout
assert_equal 25, client.ssl_config.timeout
end
end
end
end

View File

@ -16,5 +16,17 @@ module Adapters
end if ssl_mode?
end
def test_custom_adapter_config
url = URI('https://example.com:1234')
adapter = Faraday::Adapter::NetHttpPersistent.new do |http|
http.idle_timeout = 123
end
http = adapter.net_http_connection(:url => url, :request => {})
adapter.configure_request(http, {})
assert_equal 123, http.idle_timeout
end
end
end

View File

@ -40,5 +40,17 @@ module Adapters
assert_equal 1234, http.port
end
def test_custom_adapter_config
url = URI('https://example.com:1234')
adapter = Faraday::Adapter::NetHttp.new do |http|
http.continue_timeout = 123
end
http = adapter.net_http_connection(:url => url, :request => {})
adapter.configure_request(http, {})
assert_equal 123, http.continue_timeout
end
end
end

View File

@ -17,5 +17,15 @@ module Adapters
undef :test_GET_ssl_fails_with_bad_cert if ssl_mode?
end
end
def test_custom_adapter_config
adapter = Faraday::Adapter::Patron.new do |session|
session.max_redirects = 10
end
session = adapter.create_session
assert_equal 10, session.max_redirects
end
end
end