faraday 0.9.1 → 0.17.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +212 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +203 -28
  5. data/Rakefile +6 -64
  6. data/lib/faraday/adapter/em_http.rb +17 -11
  7. data/lib/faraday/adapter/em_http_ssl_patch.rb +1 -1
  8. data/lib/faraday/adapter/em_synchrony.rb +19 -5
  9. data/lib/faraday/adapter/excon.rb +13 -11
  10. data/lib/faraday/adapter/httpclient.rb +31 -9
  11. data/lib/faraday/adapter/net_http.rb +36 -14
  12. data/lib/faraday/adapter/net_http_persistent.rb +37 -17
  13. data/lib/faraday/adapter/patron.rb +44 -21
  14. data/lib/faraday/adapter/rack.rb +1 -1
  15. data/lib/faraday/adapter/test.rb +79 -28
  16. data/lib/faraday/adapter/typhoeus.rb +4 -115
  17. data/lib/faraday/adapter.rb +10 -1
  18. data/lib/faraday/autoload.rb +1 -1
  19. data/lib/faraday/connection.rb +72 -20
  20. data/lib/faraday/deprecate.rb +107 -0
  21. data/lib/faraday/error.rb +132 -27
  22. data/lib/faraday/options.rb +45 -22
  23. data/lib/faraday/parameters.rb +56 -39
  24. data/lib/faraday/rack_builder.rb +29 -4
  25. data/lib/faraday/request/authorization.rb +1 -2
  26. data/lib/faraday/request/multipart.rb +7 -2
  27. data/lib/faraday/request/retry.rb +84 -19
  28. data/lib/faraday/request.rb +22 -0
  29. data/lib/faraday/response/logger.rb +29 -8
  30. data/lib/faraday/response/raise_error.rb +7 -3
  31. data/lib/faraday/response.rb +9 -5
  32. data/lib/faraday/utils.rb +32 -3
  33. data/lib/faraday.rb +15 -36
  34. data/spec/faraday/deprecate_spec.rb +69 -0
  35. data/spec/faraday/error_spec.rb +102 -0
  36. data/spec/faraday/response/raise_error_spec.rb +106 -0
  37. data/spec/spec_helper.rb +105 -0
  38. data/test/adapters/em_http_test.rb +10 -0
  39. data/test/adapters/em_synchrony_test.rb +22 -10
  40. data/test/adapters/excon_test.rb +10 -0
  41. data/test/adapters/httpclient_test.rb +14 -1
  42. data/test/adapters/integration.rb +17 -8
  43. data/test/adapters/logger_test.rb +65 -11
  44. data/test/adapters/net_http_persistent_test.rb +96 -2
  45. data/test/adapters/net_http_test.rb +67 -2
  46. data/test/adapters/patron_test.rb +28 -8
  47. data/test/adapters/rack_test.rb +8 -1
  48. data/test/adapters/test_middleware_test.rb +46 -3
  49. data/test/adapters/typhoeus_test.rb +19 -9
  50. data/test/composite_read_io_test.rb +16 -18
  51. data/test/connection_test.rb +294 -78
  52. data/test/env_test.rb +55 -5
  53. data/test/helper.rb +11 -17
  54. data/test/middleware/retry_test.rb +115 -10
  55. data/test/middleware_stack_test.rb +97 -10
  56. data/test/options_test.rb +97 -16
  57. data/test/parameters_test.rb +94 -1
  58. data/test/request_middleware_test.rb +24 -40
  59. data/test/response_middleware_test.rb +4 -4
  60. data/test/utils_test.rb +40 -0
  61. metadata +21 -66
  62. data/.document +0 -6
  63. data/CONTRIBUTING.md +0 -36
  64. data/Gemfile +0 -25
  65. data/faraday.gemspec +0 -34
  66. data/script/cached-bundle +0 -46
  67. data/script/console +0 -7
  68. data/script/generate_certs +0 -42
  69. data/script/package +0 -7
  70. data/script/proxy-server +0 -42
  71. data/script/release +0 -17
  72. data/script/s3-put +0 -71
  73. data/script/server +0 -36
  74. data/script/test +0 -172
@@ -124,9 +124,9 @@ module Faraday
124
124
  end
125
125
  rescue EventMachine::Connectify::CONNECTError => err
126
126
  if err.message.include?("Proxy Authentication Required")
127
- raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
127
+ raise Faraday::ConnectionFailed, %{407 "Proxy Authentication Required "}
128
128
  else
129
- raise Error::ConnectionFailed, err
129
+ raise Faraday::ConnectionFailed, err
130
130
  end
131
131
  rescue => err
132
132
  if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err
@@ -138,9 +138,11 @@ module Faraday
138
138
 
139
139
  # TODO: reuse the connection to support pipelining
140
140
  def perform_single_request(env)
141
- req = EventMachine::HttpRequest.new(env[:url], connection_config(env))
141
+ req = create_request(env)
142
142
  req.setup_request(env[:method], request_config(env)).callback { |client|
143
- save_response(env, client.response_header.status, client.response) do |resp_headers|
143
+ status = client.response_header.status
144
+ reason = client.response_header.http_reason
145
+ save_response(env, status, client.response, nil, reason) do |resp_headers|
144
146
  client.response_header.each do |name, value|
145
147
  resp_headers[name.to_sym] = value
146
148
  end
@@ -148,20 +150,24 @@ module Faraday
148
150
  }
149
151
  end
150
152
 
153
+ def create_request(env)
154
+ EventMachine::HttpRequest.new(env[:url], connection_config(env).merge(@connection_options))
155
+ end
156
+
151
157
  def error_message(client)
152
158
  client.error or "request failed"
153
159
  end
154
160
 
155
161
  def raise_error(msg)
156
- errklass = Faraday::Error::ClientError
162
+ errklass = Faraday::ClientError
157
163
  if msg == Errno::ETIMEDOUT
158
- errklass = Faraday::Error::TimeoutError
164
+ errklass = Faraday::TimeoutError
159
165
  msg = "request timed out"
160
166
  elsif msg == Errno::ECONNREFUSED
161
- errklass = Faraday::Error::ConnectionFailed
167
+ errklass = Faraday::ConnectionFailed
162
168
  msg = "connection refused"
163
169
  elsif msg == "connection closed by server"
164
- errklass = Faraday::Error::ConnectionFailed
170
+ errklass = Faraday::ConnectionFailed
165
171
  end
166
172
  raise errklass, msg
167
173
  end
@@ -187,11 +193,11 @@ module Faraday
187
193
 
188
194
  def running?() @running end
189
195
 
190
- def add
196
+ def add(&block)
191
197
  if running?
192
198
  perform_request { yield }
193
199
  else
194
- @registered_procs << Proc.new
200
+ @registered_procs << block
195
201
  end
196
202
  @num_registered += 1
197
203
  end
@@ -205,7 +211,7 @@ module Faraday
205
211
  end
206
212
  end
207
213
  if @errors.size > 0
208
- raise Faraday::Error::ClientError, @errors.first || "connection failed"
214
+ raise Faraday::ClientError, @errors.first || "connection failed"
209
215
  end
210
216
  end
211
217
  ensure
@@ -39,7 +39,7 @@ module EmHttpSslPatch
39
39
  end
40
40
 
41
41
  def host
42
- parent.connopts.host
42
+ parent.uri.host
43
43
  end
44
44
 
45
45
  def certificate_store
@@ -19,7 +19,7 @@ module Faraday
19
19
 
20
20
  def call(env)
21
21
  super
22
- request = EventMachine::HttpRequest.new(Utils::URI(env[:url].to_s), connection_config(env))
22
+ request = create_request(env)
23
23
 
24
24
  http_method = env[:method].to_s.downcase.to_sym
25
25
 
@@ -54,7 +54,9 @@ module Faraday
54
54
 
55
55
  raise client.error if client.error
56
56
 
57
- save_response(env, client.response_header.status, client.response) do |resp_headers|
57
+ status = client.response_header.status
58
+ reason = client.response_header.http_reason
59
+ save_response(env, status, client.response, nil, reason) do |resp_headers|
58
60
  client.response_header.each do |name, value|
59
61
  resp_headers[name.to_sym] = value
60
62
  end
@@ -63,12 +65,20 @@ module Faraday
63
65
 
64
66
  @app.call env
65
67
  rescue Errno::ECONNREFUSED
66
- raise Error::ConnectionFailed, $!
68
+ raise Faraday::ConnectionFailed, $!
67
69
  rescue EventMachine::Connectify::CONNECTError => err
68
70
  if err.message.include?("Proxy Authentication Required")
69
- raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
71
+ raise Faraday::ConnectionFailed, %{407 "Proxy Authentication Required "}
70
72
  else
71
- raise Error::ConnectionFailed, err
73
+ raise Faraday::ConnectionFailed, err
74
+ end
75
+ rescue Errno::ETIMEDOUT => err
76
+ raise Faraday::TimeoutError, err
77
+ rescue RuntimeError => err
78
+ if err.message == "connection closed by server"
79
+ raise Faraday::ConnectionFailed, err
80
+ else
81
+ raise
72
82
  end
73
83
  rescue => err
74
84
  if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err
@@ -77,6 +87,10 @@ module Faraday
77
87
  raise
78
88
  end
79
89
  end
90
+
91
+ def create_request(env)
92
+ EventMachine::HttpRequest.new(Utils::URI(env[:url].to_s), connection_config(env).merge(@connection_options))
93
+ end
80
94
  end
81
95
  end
82
96
  end
@@ -3,11 +3,6 @@ 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
-
11
6
  def call(env)
12
7
  super
13
8
 
@@ -20,6 +15,9 @@ module Faraday
20
15
  opts[:client_key] = ssl[:client_key] if ssl[:client_key]
21
16
  opts[:certificate] = ssl[:certificate] if ssl[:certificate]
22
17
  opts[:private_key] = ssl[:private_key] if ssl[:private_key]
18
+ opts[:ssl_version] = ssl[:version] if ssl[:version]
19
+ opts[:ssl_min_version] = ssl[:min_version] if ssl[:min_version]
20
+ opts[:ssl_max_version] = ssl[:max_version] if ssl[:max_version]
23
21
 
24
22
  # https://github.com/geemus/excon/issues/106
25
23
  # https://github.com/jruby/jruby-ossl/issues/19
@@ -35,12 +33,12 @@ module Faraday
35
33
 
36
34
  if req[:open_timeout]
37
35
  opts[:connect_timeout] = req[:open_timeout]
38
- opts[:write_timeout] = req[:open_timeout]
39
36
  end
40
37
 
41
38
  if req[:proxy]
42
39
  opts[:proxy] = {
43
40
  :host => req[:proxy][:uri].host,
41
+ :hostname => req[:proxy][:uri].hostname,
44
42
  :port => req[:proxy][:uri].port,
45
43
  :scheme => req[:proxy][:uri].scheme,
46
44
  :user => req[:proxy][:user],
@@ -49,26 +47,30 @@ module Faraday
49
47
  end
50
48
  end
51
49
 
52
- conn = ::Excon.new(env[:url].to_s, opts.merge(@connection_options))
50
+ conn = create_connection(env, opts)
53
51
 
54
52
  resp = conn.request \
55
53
  :method => env[:method].to_s.upcase,
56
54
  :headers => env[:request_headers],
57
55
  :body => read_body(env)
58
56
 
59
- save_response(env, resp.status.to_i, resp.body, resp.headers)
57
+ save_response(env, resp.status.to_i, resp.body, resp.headers, resp.reason_phrase)
60
58
 
61
59
  @app.call env
62
60
  rescue ::Excon::Errors::SocketError => err
63
61
  if err.message =~ /\btimeout\b/
64
- raise Error::TimeoutError, err
62
+ raise Faraday::TimeoutError, err
65
63
  elsif err.message =~ /\bcertificate\b/
66
64
  raise Faraday::SSLError, err
67
65
  else
68
- raise Error::ConnectionFailed, err
66
+ raise Faraday::ConnectionFailed, err
69
67
  end
70
68
  rescue ::Excon::Errors::Timeout => err
71
- raise Error::TimeoutError, err
69
+ raise Faraday::TimeoutError, err
70
+ end
71
+
72
+ def create_connection(env, opts)
73
+ ::Excon.new(env[:url].to_s, opts.merge(@connection_options))
72
74
  end
73
75
 
74
76
  # TODO: support streaming requests
@@ -10,6 +10,9 @@ module Faraday
10
10
  def call(env)
11
11
  super
12
12
 
13
+ # enable compression
14
+ client.transparent_gzip_decompression = true
15
+
13
16
  if req = env[:request]
14
17
  if proxy = req[:proxy]
15
18
  configure_proxy proxy
@@ -26,6 +29,8 @@ module Faraday
26
29
  configure_ssl ssl
27
30
  end
28
31
 
32
+ configure_client
33
+
29
34
  # TODO Don't stream yet.
30
35
  # https://github.com/nahi/httpclient/pull/90
31
36
  env[:body] = env[:body].read if env[:body].respond_to? :read
@@ -34,19 +39,19 @@ module Faraday
34
39
  :body => env[:body],
35
40
  :header => env[:request_headers]
36
41
 
37
- save_response env, resp.status, resp.body, resp.headers
42
+ save_response env, resp.status, resp.body, resp.headers, resp.reason
38
43
 
39
44
  @app.call env
40
- rescue ::HTTPClient::TimeoutError
41
- raise Faraday::Error::TimeoutError, $!
45
+ rescue ::HTTPClient::TimeoutError, Errno::ETIMEDOUT
46
+ raise Faraday::TimeoutError, $!
42
47
  rescue ::HTTPClient::BadResponseError => err
43
48
  if err.message.include?('status 407')
44
- raise Faraday::Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
49
+ raise Faraday::ConnectionFailed, %{407 "Proxy Authentication Required "}
45
50
  else
46
- raise Faraday::Error::ClientError, $!
51
+ raise Faraday::ClientError, $!
47
52
  end
48
- rescue Errno::ECONNREFUSED, EOFError
49
- raise Faraday::Error::ConnectionFailed, $!
53
+ rescue Errno::ECONNREFUSED, IOError, SocketError
54
+ raise Faraday::ConnectionFailed, $!
50
55
  rescue => err
51
56
  if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err
52
57
  raise Faraday::SSLError, err
@@ -69,14 +74,14 @@ module Faraday
69
74
 
70
75
  def configure_ssl(ssl)
71
76
  ssl_config = client.ssl_config
77
+ ssl_config.verify_mode = ssl_verify_mode(ssl)
78
+ ssl_config.cert_store = ssl_cert_store(ssl)
72
79
 
73
80
  ssl_config.add_trust_ca ssl[:ca_file] if ssl[:ca_file]
74
81
  ssl_config.add_trust_ca ssl[:ca_path] if ssl[:ca_path]
75
- ssl_config.cert_store = ssl[:cert_store] if ssl[:cert_store]
76
82
  ssl_config.client_cert = ssl[:client_cert] if ssl[:client_cert]
77
83
  ssl_config.client_key = ssl[:client_key] if ssl[:client_key]
78
84
  ssl_config.verify_depth = ssl[:verify_depth] if ssl[:verify_depth]
79
- ssl_config.verify_mode = ssl_verify_mode(ssl)
80
85
  end
81
86
 
82
87
  def configure_timeouts(req)
@@ -92,6 +97,23 @@ module Faraday
92
97
  end
93
98
  end
94
99
 
100
+ def configure_client
101
+ @config_block.call(client) if @config_block
102
+ end
103
+
104
+ def ssl_cert_store(ssl)
105
+ return ssl[:cert_store] if ssl[:cert_store]
106
+ # Memoize the cert store so that the same one is passed to
107
+ # HTTPClient each time, to avoid resyncing SSL sesions when
108
+ # it's changed
109
+ @cert_store ||= begin
110
+ # Use the default cert store by default, i.e. system ca certs
111
+ cert_store = OpenSSL::X509::Store.new
112
+ cert_store.set_default_paths
113
+ cert_store
114
+ end
115
+ end
116
+
95
117
  def ssl_verify_mode(ssl)
96
118
  ssl[:verify_mode] || begin
97
119
  if ssl.fetch(:verify, true)
@@ -10,13 +10,14 @@ module Faraday
10
10
  class Adapter
11
11
  class NetHttp < Faraday::Adapter
12
12
  NET_HTTP_EXCEPTIONS = [
13
- EOFError,
13
+ IOError,
14
14
  Errno::ECONNABORTED,
15
15
  Errno::ECONNREFUSED,
16
16
  Errno::ECONNRESET,
17
17
  Errno::EHOSTUNREACH,
18
18
  Errno::EINVAL,
19
19
  Errno::ENETUNREACH,
20
+ Errno::EPIPE,
20
21
  Net::HTTPBadResponse,
21
22
  Net::HTTPHeaderSyntaxError,
22
23
  Net::ProtocolError,
@@ -27,14 +28,16 @@ module Faraday
27
28
  NET_HTTP_EXCEPTIONS << OpenSSL::SSL::SSLError if defined?(OpenSSL)
28
29
  NET_HTTP_EXCEPTIONS << Net::OpenTimeout if defined?(Net::OpenTimeout)
29
30
 
31
+ def initialize(app = nil, opts = {}, &block)
32
+ @cert_store = nil
33
+ super(app, opts, &block)
34
+ end
35
+
30
36
  def call(env)
31
37
  super
32
38
  with_net_http_connection(env) do |http|
33
39
  configure_ssl(http, env[:ssl]) if env[:url].scheme == 'https' and env[:ssl]
34
-
35
- req = env[:request]
36
- http.read_timeout = http.open_timeout = req[:timeout] if req[:timeout]
37
- http.open_timeout = req[:open_timeout] if req[:open_timeout]
40
+ configure_request(http, env[:request])
38
41
 
39
42
  begin
40
43
  http_response = perform_request(http, env)
@@ -42,11 +45,11 @@ module Faraday
42
45
  if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err
43
46
  raise Faraday::SSLError, err
44
47
  else
45
- raise Error::ConnectionFailed, err
48
+ raise Faraday::ConnectionFailed, err
46
49
  end
47
50
  end
48
51
 
49
- save_response(env, http_response.code.to_i, http_response.body || '') do |response_headers|
52
+ save_response(env, http_response.code.to_i, http_response.body || '', nil, http_response.message) do |response_headers|
50
53
  http_response.each_header do |key, value|
51
54
  response_headers[key] = value
52
55
  end
@@ -54,10 +57,12 @@ module Faraday
54
57
  end
55
58
 
56
59
  @app.call env
57
- rescue Timeout::Error => err
58
- raise Faraday::Error::TimeoutError, err
60
+ rescue Timeout::Error, Errno::ETIMEDOUT => err
61
+ raise Faraday::TimeoutError, err
59
62
  end
60
63
 
64
+ private
65
+
61
66
  def create_request(env)
62
67
  request = Net::HTTPGenericRequest.new \
63
68
  env[:method].to_s.upcase, # request method
@@ -89,10 +94,10 @@ module Faraday
89
94
 
90
95
  def net_http_connection(env)
91
96
  if proxy = env[:request][:proxy]
92
- Net::HTTP::Proxy(proxy[:uri].host, proxy[:uri].port, proxy[:user], proxy[:password])
97
+ Net::HTTP::Proxy(proxy[:uri].hostname, proxy[:uri].port, proxy[:user], proxy[:password])
93
98
  else
94
99
  Net::HTTP
95
- end.new(env[:url].host, env[:url].port)
100
+ end.new(env[:url].hostname, env[:url].port || (env[:url].scheme == 'https' ? 443 : 80))
96
101
  end
97
102
 
98
103
  def configure_ssl(http, ssl)
@@ -106,14 +111,31 @@ module Faraday
106
111
  http.ca_path = ssl[:ca_path] if ssl[:ca_path]
107
112
  http.verify_depth = ssl[:verify_depth] if ssl[:verify_depth]
108
113
  http.ssl_version = ssl[:version] if ssl[:version]
114
+ http.min_version = ssl[:min_version] if ssl[:min_version]
115
+ http.max_version = ssl[:max_version] if ssl[:max_version]
116
+ end
117
+
118
+ def configure_request(http, req)
119
+ if req[:timeout]
120
+ http.read_timeout = req[:timeout]
121
+ http.open_timeout = req[:timeout]
122
+ http.write_timeout = req[:timeout] if http.respond_to?(:write_timeout=)
123
+ end
124
+ http.open_timeout = req[:open_timeout] if req[:open_timeout]
125
+ http.write_timeout = req[:write_timeout] if req[:write_timeout] && http.respond_to?(:write_timeout=)
126
+ # Only set if Net::Http supports it, since Ruby 2.5.
127
+ http.max_retries = 0 if http.respond_to?(:max_retries=)
128
+
129
+ @config_block.call(http) if @config_block
109
130
  end
110
131
 
111
132
  def ssl_cert_store(ssl)
112
133
  return ssl[:cert_store] if ssl[:cert_store]
134
+ return @cert_store if @cert_store
113
135
  # Use the default cert store by default, i.e. system ca certs
114
- cert_store = OpenSSL::X509::Store.new
115
- cert_store.set_default_paths
116
- cert_store
136
+ @cert_store = OpenSSL::X509::Store.new
137
+ @cert_store.set_default_paths
138
+ @cert_store
117
139
  end
118
140
 
119
141
  def ssl_verify_mode(ssl)
@@ -1,15 +1,28 @@
1
- # Rely on autoloading instead of explicit require; helps avoid the "already
2
- # initialized constant" warning on Ruby 1.8.7 when NetHttp is refereced below.
3
- # require 'faraday/adapter/net_http'
4
-
5
1
  module Faraday
6
2
  class Adapter
7
- # Experimental adapter for net-http-persistent
8
3
  class NetHttpPersistent < NetHttp
9
4
  dependency 'net/http/persistent'
10
5
 
11
- def with_net_http_connection(env)
12
- if proxy = env[:request][:proxy]
6
+ private
7
+
8
+ def net_http_connection(env)
9
+ @cached_connection ||=
10
+ if Net::HTTP::Persistent.instance_method(:initialize).parameters.first == [:key, :name]
11
+ options = {name: 'Faraday'}
12
+ options[:pool_size] = @connection_options[:pool_size] if @connection_options.key?(:pool_size)
13
+ Net::HTTP::Persistent.new(**options)
14
+ else
15
+ Net::HTTP::Persistent.new('Faraday')
16
+ end
17
+
18
+ proxy_uri = proxy_uri(env)
19
+ @cached_connection.proxy = proxy_uri if @cached_connection.proxy_uri != proxy_uri
20
+ @cached_connection
21
+ end
22
+
23
+ def proxy_uri(env)
24
+ proxy_uri = nil
25
+ if (proxy = env[:request][:proxy])
13
26
  proxy_uri = ::URI::HTTP === proxy[:uri] ? proxy[:uri].dup : ::URI.parse(proxy[:uri].to_s)
14
27
  proxy_uri.user = proxy_uri.password = nil
15
28
  # awful patch for net-http-persistent 2.8 not unescaping user/password
@@ -18,30 +31,37 @@ module Faraday
18
31
  define_method(:password) { proxy[:password] }
19
32
  end if proxy[:user]
20
33
  end
21
-
22
- yield Net::HTTP::Persistent.new 'Faraday', proxy_uri
34
+ proxy_uri
23
35
  end
24
36
 
25
37
  def perform_request(http, env)
26
38
  http.request env[:url], create_request(env)
39
+ rescue Errno::ETIMEDOUT => error
40
+ raise Faraday::TimeoutError, error
27
41
  rescue Net::HTTP::Persistent::Error => error
28
42
  if error.message.include? 'Timeout'
29
- raise Faraday::Error::TimeoutError, error
43
+ raise Faraday::TimeoutError, error
30
44
  elsif error.message.include? 'connection refused'
31
- raise Faraday::Error::ConnectionFailed, error
45
+ raise Faraday::ConnectionFailed, error
32
46
  else
33
47
  raise
34
48
  end
35
49
  end
36
50
 
37
51
  def configure_ssl(http, ssl)
38
- http.verify_mode = ssl_verify_mode(ssl)
39
- http.cert_store = ssl_cert_store(ssl)
52
+ http_set(http, :verify_mode, ssl_verify_mode(ssl))
53
+ http_set(http, :cert_store, ssl_cert_store(ssl))
54
+
55
+ http_set(http, :certificate, ssl[:client_cert]) if ssl[:client_cert]
56
+ http_set(http, :private_key, ssl[:client_key]) if ssl[:client_key]
57
+ http_set(http, :ca_file, ssl[:ca_file]) if ssl[:ca_file]
58
+ http_set(http, :ssl_version, ssl[:version]) if ssl[:version]
59
+ end
40
60
 
41
- http.certificate = ssl[:client_cert] if ssl[:client_cert]
42
- http.private_key = ssl[:client_key] if ssl[:client_key]
43
- http.ca_file = ssl[:ca_file] if ssl[:ca_file]
44
- http.ssl_version = ssl[:version] if ssl[:version]
61
+ def http_set(http, attr, value)
62
+ if http.send(attr) != value
63
+ http.send("#{attr}=", value)
64
+ end
45
65
  end
46
66
  end
47
67
  end
@@ -3,18 +3,14 @@ module Faraday
3
3
  class Patron < Faraday::Adapter
4
4
  dependency 'patron'
5
5
 
6
- def initialize(app, &block)
7
- super(app)
8
- @block = block
9
- end
10
-
11
6
  def call(env)
12
7
  super
13
-
14
8
  # TODO: support streaming requests
15
9
  env[:body] = env[:body].read if env[:body].respond_to? :read
16
10
 
17
- session = @session ||= create_session
11
+ session = ::Patron::Session.new
12
+ @config_block.call(session) if @config_block
13
+ configure_ssl(session, env[:ssl]) if env[:url].scheme == 'https' and env[:ssl]
18
14
 
19
15
  if req = env[:request]
20
16
  session.timeout = session.connect_timeout = req[:timeout] if req[:timeout]
@@ -32,23 +28,26 @@ module Faraday
32
28
  data = env[:body] ? env[:body].to_s : nil
33
29
  session.request(env[:method], env[:url].to_s, env[:request_headers], :data => data)
34
30
  rescue Errno::ECONNREFUSED, ::Patron::ConnectionFailed
35
- raise Error::ConnectionFailed, $!
31
+ raise Faraday::ConnectionFailed, $!
36
32
  end
37
33
 
38
- save_response(env, response.status, response.body, response.headers)
34
+ # Remove the "HTTP/1.1 200", leaving just the reason phrase
35
+ reason_phrase = response.status_line.gsub(/^.* \d{3} /, '')
36
+
37
+ save_response(env, response.status, response.body, response.headers, reason_phrase)
39
38
 
40
39
  @app.call env
41
40
  rescue ::Patron::TimeoutError => err
42
- if err.message == "Connection time-out"
43
- raise Faraday::Error::ConnectionFailed, err
41
+ if connection_timed_out_message?(err.message)
42
+ raise Faraday::ConnectionFailed, err
44
43
  else
45
- raise Faraday::Error::TimeoutError, err
44
+ raise Faraday::TimeoutError, err
46
45
  end
47
46
  rescue ::Patron::Error => err
48
47
  if err.message.include?("code 407")
49
- raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
48
+ raise Faraday::ConnectionFailed, %{407 "Proxy Authentication Required "}
50
49
  else
51
- raise Error::ConnectionFailed, err
50
+ raise Faraday::ConnectionFailed, err
52
51
  end
53
52
  end
54
53
 
@@ -56,17 +55,41 @@ module Faraday
56
55
  # HAX: helps but doesn't work completely
57
56
  # https://github.com/toland/patron/issues/34
58
57
  ::Patron::Request::VALID_ACTIONS.tap do |actions|
59
- actions << :patch unless actions.include? :patch
60
- actions << :options unless actions.include? :options
58
+ if actions[0].is_a?(Symbol)
59
+ actions << :patch unless actions.include? :patch
60
+ actions << :options unless actions.include? :options
61
+ else
62
+ # Patron 0.4.20 and up
63
+ actions << "PATCH" unless actions.include? "PATCH"
64
+ actions << "OPTIONS" unless actions.include? "OPTIONS"
65
+ end
61
66
  end
62
67
  end
63
68
 
64
- def create_session
65
- session = ::Patron::Session.new
66
- session.insecure = true
67
- @block.call(session) if @block
68
- session
69
+ def configure_ssl(session, ssl)
70
+ if ssl.fetch(:verify, true)
71
+ session.cacert = ssl[:ca_file]
72
+ else
73
+ session.insecure = true
74
+ end
69
75
  end
76
+
77
+ private
78
+
79
+ CURL_TIMEOUT_MESSAGES = [ "Connection time-out",
80
+ "Connection timed out",
81
+ "Timed out before name resolve",
82
+ "server connect has timed out",
83
+ "Resolving timed out",
84
+ "name lookup timed out",
85
+ "timed out before SSL",
86
+ "connect() timed out"
87
+ ].freeze
88
+
89
+ def connection_timed_out_message?(message)
90
+ CURL_TIMEOUT_MESSAGES.any? { |curl_message| message.include?(curl_message) }
91
+ end
92
+
70
93
  end
71
94
  end
72
95
  end
@@ -41,7 +41,7 @@ module Faraday
41
41
 
42
42
  timeout = env[:request][:timeout] || env[:request][:open_timeout]
43
43
  response = if timeout
44
- Timer.timeout(timeout, Faraday::Error::TimeoutError) { execute_request(env, rack_env) }
44
+ Timer.timeout(timeout, Faraday::TimeoutError) { execute_request(env, rack_env) }
45
45
  else
46
46
  execute_request(env, rack_env)
47
47
  end