faraday 0.8.11 → 0.9.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +6 -0
- data/CONTRIBUTING.md +36 -0
- data/Gemfile +7 -6
- data/LICENSE.md +1 -1
- data/README.md +38 -51
- data/Rakefile +2 -18
- data/faraday.gemspec +34 -0
- data/lib/faraday.rb +181 -67
- data/lib/faraday/adapter.rb +19 -34
- data/lib/faraday/adapter/em_http.rb +24 -10
- data/lib/faraday/adapter/em_synchrony.rb +1 -15
- data/lib/faraday/adapter/excon.rb +6 -12
- data/lib/faraday/adapter/httpclient.rb +92 -0
- data/lib/faraday/adapter/net_http.rb +2 -3
- data/lib/faraday/adapter/net_http_persistent.rb +3 -15
- data/lib/faraday/adapter/patron.rb +13 -21
- data/lib/faraday/adapter/rack.rb +0 -2
- data/lib/faraday/adapter/test.rb +35 -36
- data/lib/faraday/adapter/typhoeus.rb +10 -12
- data/lib/faraday/autoload.rb +87 -0
- data/lib/faraday/connection.rb +196 -99
- data/lib/faraday/error.rb +33 -33
- data/lib/faraday/options.rb +215 -0
- data/lib/faraday/parameters.rb +193 -0
- data/lib/faraday/{builder.rb → rack_builder.rb} +78 -21
- data/lib/faraday/request.rb +12 -25
- data/lib/faraday/request/authorization.rb +3 -3
- data/lib/faraday/request/basic_authentication.rb +1 -1
- data/lib/faraday/request/instrumentation.rb +38 -0
- data/lib/faraday/request/multipart.rb +10 -9
- data/lib/faraday/request/retry.rb +70 -6
- data/lib/faraday/request/token_authentication.rb +2 -2
- data/lib/faraday/request/url_encoded.rb +7 -6
- data/lib/faraday/response.rb +17 -22
- data/lib/faraday/response/logger.rb +4 -4
- data/lib/faraday/response/raise_error.rb +4 -5
- data/lib/faraday/utils.rb +54 -67
- data/script/console +7 -0
- data/script/release +6 -3
- data/script/server +3 -1
- data/script/test +7 -33
- data/test/adapters/em_http_test.rb +6 -1
- data/test/adapters/em_synchrony_test.rb +7 -1
- data/test/adapters/excon_test.rb +0 -7
- data/test/adapters/httpclient_test.rb +16 -0
- data/test/adapters/integration.rb +8 -39
- data/test/adapters/logger_test.rb +1 -1
- data/test/adapters/net_http_test.rb +0 -31
- data/test/adapters/patron_test.rb +1 -1
- data/test/adapters/rack_test.rb +0 -5
- data/test/adapters/test_middleware_test.rb +19 -4
- data/test/adapters/typhoeus_test.rb +20 -3
- data/test/authentication_middleware_test.rb +7 -7
- data/test/connection_test.rb +52 -75
- data/test/env_test.rb +33 -24
- data/test/helper.rb +15 -13
- data/test/live_server.rb +10 -4
- data/test/middleware/instrumentation_test.rb +75 -0
- data/test/middleware/retry_test.rb +44 -38
- data/test/middleware_stack_test.rb +12 -11
- data/test/options_test.rb +126 -0
- data/test/request_middleware_test.rb +17 -7
- data/test/response_middleware_test.rb +2 -4
- data/test/strawberry.rb +2 -0
- metadata +82 -28
- checksums.yaml +0 -7
- data/script/proxy-server +0 -41
- data/test/multibyte.txt +0 -1
- data/test/parameters_test.rb +0 -24
- data/test/utils_test.rb +0 -30
data/lib/faraday/adapter.rb
CHANGED
@@ -1,32 +1,22 @@
|
|
1
1
|
module Faraday
|
2
|
+
# Public: This is a base class for all Faraday adapters. Adapters are
|
3
|
+
# responsible for fulfilling a Faraday request.
|
2
4
|
class Adapter < Middleware
|
3
5
|
CONTENT_LENGTH = 'Content-Length'.freeze
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
:
|
10
|
-
:
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:
|
14
|
-
:
|
15
|
-
:
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
register_middleware \
|
20
|
-
:test => :Test,
|
21
|
-
:net_http => :NetHttp,
|
22
|
-
:net_http_persistent => :NetHttpPersistent,
|
23
|
-
:typhoeus => :Typhoeus,
|
24
|
-
:patron => :Patron,
|
25
|
-
:em_synchrony => :EMSynchrony,
|
26
|
-
:em_http => :EMHttp,
|
27
|
-
:excon => :Excon,
|
28
|
-
:rack => :Rack
|
29
|
-
|
7
|
+
register_middleware File.expand_path('../adapter', __FILE__),
|
8
|
+
:test => [:Test, 'test'],
|
9
|
+
:net_http => [:NetHttp, 'net_http'],
|
10
|
+
:net_http_persistent => [:NetHttpPersistent, 'net_http_persistent'],
|
11
|
+
:typhoeus => [:Typhoeus, 'typhoeus'],
|
12
|
+
:patron => [:Patron, 'patron'],
|
13
|
+
:em_synchrony => [:EMSynchrony, 'em_synchrony'],
|
14
|
+
:em_http => [:EMHttp, 'em_http'],
|
15
|
+
:excon => [:Excon, 'excon'],
|
16
|
+
:rack => [:Rack, 'rack'],
|
17
|
+
:httpclient => [:HTTPClient, 'httpclient']
|
18
|
+
|
19
|
+
# Public: This module marks an Adapter as supporting parallel requests.
|
30
20
|
module Parallelism
|
31
21
|
attr_writer :supports_parallel
|
32
22
|
def supports_parallel?() @supports_parallel end
|
@@ -41,18 +31,13 @@ module Faraday
|
|
41
31
|
self.supports_parallel = false
|
42
32
|
|
43
33
|
def call(env)
|
44
|
-
if
|
45
|
-
# play nice and indicate we're sending an empty body
|
46
|
-
env[:request_headers][CONTENT_LENGTH] = "0"
|
47
|
-
# Typhoeus hangs on PUT requests if body is nil
|
48
|
-
env[:body] = ''
|
49
|
-
end
|
34
|
+
env.clear_body if env.needs_body?
|
50
35
|
end
|
51
36
|
|
52
37
|
def save_response(env, status, body, headers = nil)
|
53
|
-
env
|
54
|
-
env
|
55
|
-
env
|
38
|
+
env.status = status
|
39
|
+
env.body = body
|
40
|
+
env.response_headers = Utils::Headers.new.tap do |response_headers|
|
56
41
|
response_headers.update headers unless headers.nil?
|
57
42
|
yield response_headers if block_given?
|
58
43
|
end
|
@@ -7,8 +7,10 @@ module Faraday
|
|
7
7
|
module Options
|
8
8
|
def connection_config(env)
|
9
9
|
options = {}
|
10
|
+
configure_ssl(options, env)
|
10
11
|
configure_proxy(options, env)
|
11
12
|
configure_timeout(options, env)
|
13
|
+
configure_socket(options, env)
|
12
14
|
options
|
13
15
|
end
|
14
16
|
|
@@ -20,6 +22,9 @@ module Faraday
|
|
20
22
|
# :file => 'path/to/file', # stream data off disk
|
21
23
|
}
|
22
24
|
configure_compression(options, env)
|
25
|
+
# configure_proxy_auth
|
26
|
+
# :proxy => {:authorization => [user, pass]}
|
27
|
+
# proxy[:username] && proxy[:password]
|
23
28
|
options
|
24
29
|
end
|
25
30
|
|
@@ -28,12 +33,29 @@ module Faraday
|
|
28
33
|
body.respond_to?(:read) ? body.read : body
|
29
34
|
end
|
30
35
|
|
36
|
+
def configure_ssl(options, env)
|
37
|
+
if ssl = env[:ssl]
|
38
|
+
# :ssl => {
|
39
|
+
# :private_key_file => '/tmp/server.key',
|
40
|
+
# :cert_chain_file => '/tmp/server.crt',
|
41
|
+
# :verify_peer => false
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
31
45
|
def configure_proxy(options, env)
|
32
46
|
if proxy = request_options(env)[:proxy]
|
33
47
|
options[:proxy] = {
|
34
48
|
:host => proxy[:uri].host,
|
35
|
-
:port => proxy[:uri].port
|
36
|
-
|
49
|
+
:port => proxy[:uri].port
|
50
|
+
}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def configure_socket(options, env)
|
55
|
+
if bind = request_options(env)[:bind]
|
56
|
+
options[:bind] = {
|
57
|
+
:host => bind[:host],
|
58
|
+
:port => bind[:port]
|
37
59
|
}
|
38
60
|
end
|
39
61
|
end
|
@@ -102,12 +124,6 @@ module Faraday
|
|
102
124
|
}
|
103
125
|
end
|
104
126
|
end
|
105
|
-
rescue EventMachine::Connectify::CONNECTError => err
|
106
|
-
if err.message.include?("Proxy Authentication Required")
|
107
|
-
raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
|
108
|
-
else
|
109
|
-
raise Error::ConnectionFailed, err
|
110
|
-
end
|
111
127
|
end
|
112
128
|
|
113
129
|
# TODO: reuse the connection to support pipelining
|
@@ -134,8 +150,6 @@ module Faraday
|
|
134
150
|
elsif msg == Errno::ECONNREFUSED
|
135
151
|
errklass = Faraday::Error::ConnectionFailed
|
136
152
|
msg = "connection refused"
|
137
|
-
elsif msg == "connection closed by server"
|
138
|
-
errklass = Faraday::Error::ConnectionFailed
|
139
153
|
end
|
140
154
|
raise errklass, msg
|
141
155
|
end
|
@@ -19,7 +19,7 @@ module Faraday
|
|
19
19
|
|
20
20
|
def call(env)
|
21
21
|
super
|
22
|
-
request = EventMachine::HttpRequest.new(URI::parse(env[:url].to_s), connection_config(env))
|
22
|
+
request = EventMachine::HttpRequest.new(URI::parse(env[:url].to_s), connection_config(env))
|
23
23
|
|
24
24
|
http_method = env[:method].to_s.downcase.to_sym
|
25
25
|
|
@@ -52,8 +52,6 @@ module Faraday
|
|
52
52
|
client = block.call
|
53
53
|
end
|
54
54
|
|
55
|
-
raise client.error if client.error
|
56
|
-
|
57
55
|
save_response(env, client.response_header.status, client.response) do |resp_headers|
|
58
56
|
client.response_header.each do |name, value|
|
59
57
|
resp_headers[name.to_sym] = value
|
@@ -64,18 +62,6 @@ module Faraday
|
|
64
62
|
@app.call env
|
65
63
|
rescue Errno::ECONNREFUSED
|
66
64
|
raise Error::ConnectionFailed, $!
|
67
|
-
rescue EventMachine::Connectify::CONNECTError => err
|
68
|
-
if err.message.include?("Proxy Authentication Required")
|
69
|
-
raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
|
70
|
-
else
|
71
|
-
raise Error::ConnectionFailed, err
|
72
|
-
end
|
73
|
-
rescue RuntimeError => err
|
74
|
-
if err.message == "connection closed by server"
|
75
|
-
raise Error::ConnectionFailed, err
|
76
|
-
else
|
77
|
-
raise
|
78
|
-
end
|
79
65
|
end
|
80
66
|
end
|
81
67
|
end
|
@@ -3,6 +3,11 @@ module Faraday
|
|
3
3
|
class Excon < Faraday::Adapter
|
4
4
|
dependency 'excon'
|
5
5
|
|
6
|
+
def initialize(app, connection_options = {})
|
7
|
+
@connection_options = connection_options
|
8
|
+
super(app)
|
9
|
+
end
|
10
|
+
|
6
11
|
def call(env)
|
7
12
|
super
|
8
13
|
|
@@ -28,20 +33,9 @@ module Faraday
|
|
28
33
|
opts[:connect_timeout] = req[:open_timeout]
|
29
34
|
opts[:write_timeout] = req[:open_timeout]
|
30
35
|
end
|
31
|
-
|
32
|
-
if req[:proxy]
|
33
|
-
opts[:proxy] = {
|
34
|
-
:host => req[:proxy][:uri].host,
|
35
|
-
:hostname => req[:proxy][:uri].hostname,
|
36
|
-
:port => req[:proxy][:uri].port,
|
37
|
-
:scheme => req[:proxy][:uri].scheme,
|
38
|
-
:user => req[:proxy][:user],
|
39
|
-
:password => req[:proxy][:password]
|
40
|
-
}
|
41
|
-
end
|
42
36
|
end
|
43
37
|
|
44
|
-
conn = ::Excon.new(env[:url].to_s, opts)
|
38
|
+
conn = ::Excon.new(env[:url].to_s, opts.merge(@connection_options))
|
45
39
|
|
46
40
|
resp = conn.request \
|
47
41
|
:method => env[:method].to_s.upcase,
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module Faraday
|
2
|
+
class Adapter
|
3
|
+
class HTTPClient < Faraday::Adapter
|
4
|
+
dependency 'httpclient'
|
5
|
+
|
6
|
+
def client
|
7
|
+
@client ||= ::HTTPClient.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
super
|
12
|
+
|
13
|
+
if req = env[:request]
|
14
|
+
if proxy = req[:proxy]
|
15
|
+
configure_proxy proxy
|
16
|
+
end
|
17
|
+
|
18
|
+
if bind = req[:bind]
|
19
|
+
configure_socket bind
|
20
|
+
end
|
21
|
+
|
22
|
+
configure_timeouts req
|
23
|
+
end
|
24
|
+
|
25
|
+
if env[:url].scheme == 'https' && ssl = env[:ssl]
|
26
|
+
configure_ssl ssl
|
27
|
+
end
|
28
|
+
|
29
|
+
# TODO Don't stream yet.
|
30
|
+
# https://github.com/nahi/httpclient/pull/90
|
31
|
+
env[:body] = env[:body].read if env[:body].respond_to? :read
|
32
|
+
|
33
|
+
resp = client.request env[:method], env[:url],
|
34
|
+
:body => env[:body],
|
35
|
+
:header => env[:request_headers]
|
36
|
+
|
37
|
+
save_response env, resp.status, resp.body, resp.headers
|
38
|
+
|
39
|
+
@app.call env
|
40
|
+
rescue ::HTTPClient::TimeoutError
|
41
|
+
raise Faraday::Error::TimeoutError, $!
|
42
|
+
end
|
43
|
+
|
44
|
+
def configure_socket(bind)
|
45
|
+
client.socket_local.host = bind[:host]
|
46
|
+
client.socket_local.port = bind[:port]
|
47
|
+
end
|
48
|
+
|
49
|
+
def configure_proxy(proxy)
|
50
|
+
client.proxy = proxy[:uri]
|
51
|
+
if proxy[:user] && proxy[:password]
|
52
|
+
client.set_proxy_auth proxy[:user], proxy[:password]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def configure_ssl(ssl)
|
57
|
+
ssl_config = client.ssl_config
|
58
|
+
|
59
|
+
ssl_config.add_trust_ca ssl[:ca_file] if ssl[:ca_file]
|
60
|
+
ssl_config.add_trust_ca ssl[:ca_path] if ssl[:ca_path]
|
61
|
+
ssl_config.cert_store = ssl[:cert_store] if ssl[:cert_store]
|
62
|
+
ssl_config.client_cert = ssl[:client_cert] if ssl[:client_cert]
|
63
|
+
ssl_config.client_key = ssl[:client_key] if ssl[:client_key]
|
64
|
+
ssl_config.verify_depth = ssl[:verify_depth] if ssl[:verify_depth]
|
65
|
+
ssl_config.verify_mode = ssl_verify_mode(ssl)
|
66
|
+
end
|
67
|
+
|
68
|
+
def configure_timeouts(req)
|
69
|
+
if req[:timeout]
|
70
|
+
client.connect_timeout = req[:timeout]
|
71
|
+
client.receive_timeout = req[:timeout]
|
72
|
+
client.send_timeout = req[:timeout]
|
73
|
+
end
|
74
|
+
|
75
|
+
if req[:open_timeout]
|
76
|
+
client.connect_timeout = req[:open_timeout]
|
77
|
+
client.send_timeout = req[:open_timeout]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def ssl_verify_mode(ssl)
|
82
|
+
ssl[:verify_mode] || begin
|
83
|
+
if ssl.fetch(:verify, true)
|
84
|
+
OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
85
|
+
else
|
86
|
+
OpenSSL::SSL::VERIFY_NONE
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -24,7 +24,6 @@ module Faraday
|
|
24
24
|
]
|
25
25
|
|
26
26
|
NET_HTTP_EXCEPTIONS << OpenSSL::SSL::SSLError if defined?(OpenSSL)
|
27
|
-
NET_HTTP_EXCEPTIONS << Net::OpenTimeout if defined?(Net::OpenTimeout)
|
28
27
|
|
29
28
|
def call(env)
|
30
29
|
super
|
@@ -41,7 +40,7 @@ module Faraday
|
|
41
40
|
raise Error::ConnectionFailed, $!
|
42
41
|
end
|
43
42
|
|
44
|
-
save_response(env, http_response.code.to_i, http_response.body) do |response_headers|
|
43
|
+
save_response(env, http_response.code.to_i, http_response.body || '') do |response_headers|
|
45
44
|
http_response.each_header do |key, value|
|
46
45
|
response_headers[key] = value
|
47
46
|
end
|
@@ -82,7 +81,7 @@ module Faraday
|
|
82
81
|
Net::HTTP::Proxy(proxy[:uri].host, proxy[:uri].port, proxy[:user], proxy[:password])
|
83
82
|
else
|
84
83
|
Net::HTTP
|
85
|
-
end.new(env[:url].host, env[:url].port
|
84
|
+
end.new(env[:url].host, env[:url].port)
|
86
85
|
end
|
87
86
|
|
88
87
|
def configure_ssl(http, ssl)
|
@@ -1,6 +1,4 @@
|
|
1
|
-
|
2
|
-
# initialized constant" warning on Ruby 1.8.7 when NetHttp is refereced below.
|
3
|
-
# require 'faraday/adapter/net_http'
|
1
|
+
require 'faraday/adapter/net_http'
|
4
2
|
|
5
3
|
module Faraday
|
6
4
|
class Adapter
|
@@ -9,16 +7,8 @@ module Faraday
|
|
9
7
|
dependency 'net/http/persistent'
|
10
8
|
|
11
9
|
def net_http_connection(env)
|
12
|
-
|
13
|
-
|
14
|
-
proxy_uri.user = proxy_uri.password = nil
|
15
|
-
# awful patch for net-http-persistent 2.8 not unescaping user/password
|
16
|
-
(class << proxy_uri; self; end).class_eval do
|
17
|
-
define_method(:user) { proxy[:user] }
|
18
|
-
define_method(:password) { proxy[:password] }
|
19
|
-
end if proxy[:user]
|
20
|
-
end
|
21
|
-
Net::HTTP::Persistent.new 'Faraday', proxy_uri
|
10
|
+
Net::HTTP::Persistent.new 'Faraday',
|
11
|
+
env[:request][:proxy] ? env[:request][:proxy][:uri] : nil
|
22
12
|
end
|
23
13
|
|
24
14
|
def perform_request(http, env)
|
@@ -26,8 +16,6 @@ module Faraday
|
|
26
16
|
rescue Net::HTTP::Persistent::Error => error
|
27
17
|
if error.message.include? 'Timeout'
|
28
18
|
raise Faraday::Error::TimeoutError, error
|
29
|
-
elsif error.message.include? 'connection refused'
|
30
|
-
raise Faraday::Error::ConnectionFailed, error
|
31
19
|
else
|
32
20
|
raise
|
33
21
|
end
|
@@ -5,7 +5,7 @@ module Faraday
|
|
5
5
|
|
6
6
|
def initialize(app, &block)
|
7
7
|
super(app)
|
8
|
-
@block = block
|
8
|
+
@block = block if block_given?
|
9
9
|
end
|
10
10
|
|
11
11
|
def call(env)
|
@@ -19,19 +19,19 @@ module Faraday
|
|
19
19
|
if req = env[:request]
|
20
20
|
session.timeout = session.connect_timeout = req[:timeout] if req[:timeout]
|
21
21
|
session.connect_timeout = req[:open_timeout] if req[:open_timeout]
|
22
|
-
|
22
|
+
|
23
23
|
if proxy = req[:proxy]
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
session.proxy = proxy[:uri].to_s
|
25
|
+
if proxy[:user] && proxy[:password]
|
26
|
+
prepend_proxy_auth_string(proxy, session)
|
27
|
+
end
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
31
|
response = begin
|
32
32
|
data = env[:body] ? env[:body].to_s : nil
|
33
33
|
session.request(env[:method], env[:url].to_s, env[:request_headers], :data => data)
|
34
|
-
rescue Errno::ECONNREFUSED
|
34
|
+
rescue Errno::ECONNREFUSED
|
35
35
|
raise Error::ConnectionFailed, $!
|
36
36
|
end
|
37
37
|
|
@@ -40,26 +40,14 @@ module Faraday
|
|
40
40
|
@app.call env
|
41
41
|
rescue ::Patron::TimeoutError => err
|
42
42
|
raise Faraday::Error::TimeoutError, err
|
43
|
-
rescue ::Patron::Error => err
|
44
|
-
if err.message.include?("code 407")
|
45
|
-
raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
|
46
|
-
else
|
47
|
-
raise Error::ConnectionFailed, err
|
48
|
-
end
|
49
43
|
end
|
50
44
|
|
51
45
|
if loaded? && defined?(::Patron::Request::VALID_ACTIONS)
|
52
46
|
# HAX: helps but doesn't work completely
|
53
47
|
# https://github.com/toland/patron/issues/34
|
54
48
|
::Patron::Request::VALID_ACTIONS.tap do |actions|
|
55
|
-
|
56
|
-
|
57
|
-
actions << :options unless actions.include? :options
|
58
|
-
else
|
59
|
-
# Patron 0.4.20 and up
|
60
|
-
actions << "PATCH" unless actions.include? "PATCH"
|
61
|
-
actions << "OPTIONS" unless actions.include? "OPTIONS"
|
62
|
-
end
|
49
|
+
actions << :patch unless actions.include? :patch
|
50
|
+
actions << :options unless actions.include? :options
|
63
51
|
end
|
64
52
|
end
|
65
53
|
|
@@ -70,5 +58,9 @@ module Faraday
|
|
70
58
|
session
|
71
59
|
end
|
72
60
|
end
|
61
|
+
|
62
|
+
def prepend_proxy_auth_string(proxy, session)
|
63
|
+
session.proxy.insert(7, "#{proxy[:user]}:#{proxy[:password]}@")
|
64
|
+
end
|
73
65
|
end
|
74
66
|
end
|