faraday 0.16.0 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.md +1 -1
  3. data/README.md +347 -18
  4. data/lib/faraday/adapter/em_http.rb +99 -142
  5. data/lib/faraday/adapter/em_http_ssl_patch.rb +17 -23
  6. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +15 -18
  7. data/lib/faraday/adapter/em_synchrony.rb +60 -104
  8. data/lib/faraday/adapter/excon.rb +55 -100
  9. data/lib/faraday/adapter/httpclient.rb +39 -61
  10. data/lib/faraday/adapter/net_http.rb +51 -104
  11. data/lib/faraday/adapter/net_http_persistent.rb +27 -48
  12. data/lib/faraday/adapter/patron.rb +35 -54
  13. data/lib/faraday/adapter/rack.rb +12 -28
  14. data/lib/faraday/adapter/test.rb +53 -86
  15. data/lib/faraday/adapter/typhoeus.rb +1 -4
  16. data/lib/faraday/adapter.rb +22 -36
  17. data/lib/faraday/autoload.rb +36 -47
  18. data/lib/faraday/connection.rb +179 -321
  19. data/lib/faraday/error.rb +33 -67
  20. data/lib/faraday/middleware.rb +28 -4
  21. data/lib/faraday/options.rb +186 -35
  22. data/lib/faraday/parameters.rb +197 -4
  23. data/lib/faraday/rack_builder.rb +56 -67
  24. data/lib/faraday/request/authorization.rb +30 -42
  25. data/lib/faraday/request/basic_authentication.rb +7 -14
  26. data/lib/faraday/request/instrumentation.rb +27 -45
  27. data/lib/faraday/request/multipart.rb +48 -79
  28. data/lib/faraday/request/retry.rb +170 -197
  29. data/lib/faraday/request/token_authentication.rb +10 -15
  30. data/lib/faraday/request/url_encoded.rb +23 -41
  31. data/lib/faraday/request.rb +36 -68
  32. data/lib/faraday/response/logger.rb +69 -22
  33. data/lib/faraday/response/raise_error.rb +14 -36
  34. data/lib/faraday/response.rb +16 -23
  35. data/lib/faraday/upload_io.rb +67 -0
  36. data/lib/faraday/utils.rb +245 -28
  37. data/lib/faraday.rb +175 -93
  38. metadata +5 -22
  39. data/lib/faraday/adapter_registry.rb +0 -28
  40. data/lib/faraday/dependency_loader.rb +0 -37
  41. data/lib/faraday/encoders/flat_params_encoder.rb +0 -94
  42. data/lib/faraday/encoders/nested_params_encoder.rb +0 -171
  43. data/lib/faraday/file_part.rb +0 -128
  44. data/lib/faraday/logging/formatter.rb +0 -92
  45. data/lib/faraday/middleware_registry.rb +0 -129
  46. data/lib/faraday/options/connection_options.rb +0 -22
  47. data/lib/faraday/options/env.rb +0 -181
  48. data/lib/faraday/options/proxy_options.rb +0 -28
  49. data/lib/faraday/options/request_options.rb +0 -21
  50. data/lib/faraday/options/ssl_options.rb +0 -59
  51. data/lib/faraday/param_part.rb +0 -53
  52. data/lib/faraday/utils/headers.rb +0 -139
  53. data/lib/faraday/utils/params_hash.rb +0 -61
  54. data/spec/external_adapters/faraday_specs_setup.rb +0 -14
@@ -1,15 +1,10 @@
1
- # frozen_string_literal: true
2
-
3
1
  module Faraday
4
2
  class Adapter
5
- # EventMachine adapter. This adapter is useful for either asynchronous
6
- # requests when in an EM reactor loop, or for making parallel requests in
3
+ # EventMachine adapter is useful for either asynchronous requests
4
+ # when in EM reactor loop or for making parallel requests in
7
5
  # synchronous code.
8
6
  class EMHttp < Faraday::Adapter
9
- # Options is a module containing helpers to convert the Faraday env object
10
- # into options hashes for EMHTTP method calls.
11
7
  module Options
12
- # @return [Hash]
13
8
  def connection_config(env)
14
9
  options = {}
15
10
  configure_proxy(options, env)
@@ -21,10 +16,10 @@ module Faraday
21
16
 
22
17
  def request_config(env)
23
18
  options = {
24
- body: read_body(env),
25
- head: env[:request_headers]
26
- # keepalive: true,
27
- # file: 'path/to/file', # stream data off disk
19
+ :body => read_body(env),
20
+ :head => env[:request_headers],
21
+ # :keepalive => true,
22
+ # :file => 'path/to/file', # stream data off disk
28
23
  }
29
24
  configure_compression(options, env)
30
25
  options
@@ -35,53 +30,44 @@ module Faraday
35
30
  body.respond_to?(:read) ? body.read : body
36
31
  end
37
32
 
38
- # Reads out proxy settings from env into options
39
33
  def configure_proxy(options, env)
40
- proxy = request_options(env)[:proxy]
41
- return unless proxy
42
-
43
- options[:proxy] = {
44
- host: proxy[:uri].host,
45
- port: proxy[:uri].port,
46
- authorization: [proxy[:user], proxy[:password]]
47
- }
34
+ if proxy = request_options(env)[:proxy]
35
+ options[:proxy] = {
36
+ :host => proxy[:uri].host,
37
+ :port => proxy[:uri].port,
38
+ :authorization => [proxy[:user], proxy[:password]]
39
+ }
40
+ end
48
41
  end
49
42
 
50
- # Reads out host and port settings from env into options
51
43
  def configure_socket(options, env)
52
- bind = request_options(env)[:bind]
53
- return unless bind
54
-
55
- options[:bind] = {
56
- host: bind[:host],
57
- port: bind[:port]
58
- }
44
+ if bind = request_options(env)[:bind]
45
+ options[:bind] = {
46
+ :host => bind[:host],
47
+ :port => bind[:port]
48
+ }
49
+ end
59
50
  end
60
51
 
61
- # Reads out SSL certificate settings from env into options
62
52
  def configure_ssl(options, env)
63
- return unless env[:url].scheme == 'https' && env[:ssl]
64
-
65
- options[:ssl] = {
66
- cert_chain_file: env[:ssl][:ca_file],
67
- verify_peer: env[:ssl].fetch(:verify, true)
68
- }
53
+ if env[:url].scheme == 'https' && env[:ssl]
54
+ options[:ssl] = {
55
+ :cert_chain_file => env[:ssl][:ca_file],
56
+ :verify_peer => env[:ssl].fetch(:verify, true)
57
+ }
58
+ end
69
59
  end
70
60
 
71
- # Reads out timeout settings from env into options
72
61
  def configure_timeout(options, env)
73
- timeout, open_timeout = request_options(env)
74
- .values_at(:timeout, :open_timeout)
62
+ timeout, open_timeout = request_options(env).values_at(:timeout, :open_timeout)
75
63
  options[:connect_timeout] = options[:inactivity_timeout] = timeout
76
64
  options[:connect_timeout] = open_timeout if open_timeout
77
65
  end
78
66
 
79
- # Reads out compression header settings from env into options
80
67
  def configure_compression(options, env)
81
- return unless (env[:method] == :get) &&
82
- !options[:head].key?('accept-encoding')
83
-
84
- options[:head]['accept-encoding'] = 'gzip, compressed'
68
+ if env[:method] == :get and not options[:head].key? 'accept-encoding'
69
+ options[:head]['accept-encoding'] = 'gzip, compressed'
70
+ end
85
71
  end
86
72
 
87
73
  def request_options(env)
@@ -95,8 +81,7 @@ module Faraday
95
81
 
96
82
  self.supports_parallel = true
97
83
 
98
- # @return [Manager]
99
- def self.setup_parallel_manager(_options = nil)
84
+ def self.setup_parallel_manager(options = nil)
100
85
  Manager.new
101
86
  end
102
87
 
@@ -109,113 +94,95 @@ module Faraday
109
94
  def perform_request(env)
110
95
  if parallel?(env)
111
96
  manager = env[:parallel_manager]
112
- manager.add do
113
- perform_single_request(env)
114
- .callback { env[:response].finish(env) }
115
- end
116
- elsif EventMachine.reactor_running?
117
- # EM is running: instruct upstream that this is an async request
118
- env[:parallel_manager] = true
119
- perform_single_request(env)
120
- .callback { env[:response].finish(env) }
121
- .errback do
122
- # TODO: no way to communicate the error in async mode
123
- raise NotImplementedError
124
- end
97
+ manager.add {
98
+ perform_single_request(env).
99
+ callback { env[:response].finish(env) }
100
+ }
125
101
  else
126
- error = nil
127
- # start EM, block until request is completed
128
- EventMachine.run do
129
- perform_single_request(env)
130
- .callback { EventMachine.stop }
131
- .errback do |client|
132
- error = error_message(client)
133
- EventMachine.stop
134
- end
102
+ unless EventMachine.reactor_running?
103
+ error = nil
104
+ # start EM, block until request is completed
105
+ EventMachine.run do
106
+ perform_single_request(env).
107
+ callback { EventMachine.stop }.
108
+ errback { |client|
109
+ error = error_message(client)
110
+ EventMachine.stop
111
+ }
112
+ end
113
+ raise_error(error) if error
114
+ else
115
+ # EM is running: instruct upstream that this is an async request
116
+ env[:parallel_manager] = true
117
+ perform_single_request(env).
118
+ callback { env[:response].finish(env) }.
119
+ errback {
120
+ # TODO: no way to communicate the error in async mode
121
+ raise NotImplementedError
122
+ }
135
123
  end
136
- raise_error(error) if error
137
124
  end
138
- rescue EventMachine::Connectify::CONNECTError => e
139
- if e.message.include?('Proxy Authentication Required')
140
- raise Faraday::ConnectionFailed,
141
- %(407 "Proxy Authentication Required ")
125
+ rescue EventMachine::Connectify::CONNECTError => err
126
+ if err.message.include?("Proxy Authentication Required")
127
+ raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
128
+ else
129
+ raise Error::ConnectionFailed, err
142
130
  end
143
-
144
- raise Faraday::ConnectionFailed, e
145
- rescue StandardError => e
146
- if defined?(OpenSSL) && e.is_a?(OpenSSL::SSL::SSLError)
147
- raise Faraday::SSLError, e
131
+ rescue => err
132
+ if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err
133
+ raise Faraday::SSLError, err
134
+ else
135
+ raise
148
136
  end
149
-
150
- raise
151
137
  end
152
138
 
153
139
  # TODO: reuse the connection to support pipelining
154
140
  def perform_single_request(env)
155
141
  req = create_request(env)
156
- req = req.setup_request(env[:method], request_config(env))
157
- req.callback do |client|
158
- if env[:request].stream_response?
159
- warn "Streaming downloads for #{self.class.name} " \
160
- 'are not yet implemented.'
161
- env[:request].on_data.call(
162
- client.response,
163
- client.response.bytesize
164
- )
165
- end
142
+ req.setup_request(env[:method], request_config(env)).callback { |client|
166
143
  status = client.response_header.status
167
144
  reason = client.response_header.http_reason
168
- save_response(env, status, client.response, nil, reason) do |headers|
145
+ save_response(env, status, client.response, nil, reason) do |resp_headers|
169
146
  client.response_header.each do |name, value|
170
- headers[name.to_sym] = value
147
+ resp_headers[name.to_sym] = value
171
148
  end
172
149
  end
173
- end
150
+ }
174
151
  end
175
152
 
176
153
  def create_request(env)
177
- EventMachine::HttpRequest.new(
178
- env[:url], connection_config(env).merge(@connection_options)
179
- )
154
+ EventMachine::HttpRequest.new(env[:url], connection_config(env).merge(@connection_options))
180
155
  end
181
156
 
182
157
  def error_message(client)
183
- client.error || 'request failed'
158
+ client.error or "request failed"
184
159
  end
185
160
 
186
161
  def raise_error(msg)
187
- error_class = Faraday::ClientError
188
- if timeout_message?(msg)
189
- error_class = Faraday::TimeoutError
190
- msg = 'request timed out'
162
+ errklass = Faraday::Error::ClientError
163
+ if msg == Errno::ETIMEDOUT
164
+ errklass = Faraday::Error::TimeoutError
165
+ msg = "request timed out"
191
166
  elsif msg == Errno::ECONNREFUSED
192
- error_class = Faraday::ConnectionFailed
193
- msg = 'connection refused'
194
- elsif msg == 'connection closed by server'
195
- error_class = Faraday::ConnectionFailed
167
+ errklass = Faraday::Error::ConnectionFailed
168
+ msg = "connection refused"
169
+ elsif msg == "connection closed by server"
170
+ errklass = Faraday::Error::ConnectionFailed
196
171
  end
197
- raise error_class, msg
172
+ raise errklass, msg
198
173
  end
199
174
 
200
- def timeout_message?(msg)
201
- msg == Errno::ETIMEDOUT ||
202
- (msg.is_a?(String) && msg.include?('timeout error'))
203
- end
204
-
205
- # @return [Boolean]
206
175
  def parallel?(env)
207
176
  !!env[:parallel_manager]
208
177
  end
209
178
 
210
- # This parallel manager is designed to start an EventMachine loop
179
+ # The parallel manager is designed to start an EventMachine loop
211
180
  # and block until all registered requests have been completed.
212
181
  class Manager
213
- # @see reset
214
182
  def initialize
215
183
  reset
216
184
  end
217
185
 
218
- # Re-initializes instance variables
219
186
  def reset
220
187
  @registered_procs = []
221
188
  @num_registered = 0
@@ -224,30 +191,27 @@ module Faraday
224
191
  @running = false
225
192
  end
226
193
 
227
- # @return [Boolean]
228
- def running?
229
- @running
230
- end
194
+ def running?() @running end
231
195
 
232
- def add(&block)
196
+ def add
233
197
  if running?
234
198
  perform_request { yield }
235
199
  else
236
- @registered_procs << block
200
+ @registered_procs << Proc.new
237
201
  end
238
202
  @num_registered += 1
239
203
  end
240
204
 
241
205
  def run
242
- if @num_registered.positive?
206
+ if @num_registered > 0
243
207
  @running = true
244
208
  EventMachine.run do
245
209
  @registered_procs.each do |proc|
246
210
  perform_request(&proc)
247
211
  end
248
212
  end
249
- unless @errors.empty?
250
- raise Faraday::ClientError, @errors.first || 'connection failed'
213
+ if @errors.size > 0
214
+ raise Faraday::Error::ClientError, @errors.first || "connection failed"
251
215
  end
252
216
  end
253
217
  ensure
@@ -256,31 +220,24 @@ module Faraday
256
220
 
257
221
  def perform_request
258
222
  client = yield
259
- client.callback do
260
- @num_succeeded += 1
261
- check_finished
262
- end
263
- client.errback do
264
- @errors << client.error
265
- check_finished
266
- end
223
+ client.callback { @num_succeeded += 1; check_finished }
224
+ client.errback { @errors << client.error; check_finished }
267
225
  end
268
226
 
269
227
  def check_finished
270
- EventMachine.stop if @num_succeeded + @errors.size == @num_registered
228
+ if @num_succeeded + @errors.size == @num_registered
229
+ EventMachine.stop
230
+ end
271
231
  end
272
232
  end
273
233
  end
274
234
  end
275
235
  end
276
236
 
277
- if Faraday::Adapter::EMHttp.loaded?
278
- begin
279
- require 'openssl'
280
- rescue LoadError
281
- warn 'Warning: no such file to load -- openssl. ' \
282
- 'Make sure it is installed if you want HTTPS support'
283
- else
284
- require 'faraday/adapter/em_http_ssl_patch'
285
- end
286
- end
237
+ begin
238
+ require 'openssl'
239
+ rescue LoadError
240
+ warn "Warning: no such file to load -- openssl. Make sure it is installed if you want HTTPS support"
241
+ else
242
+ require 'faraday/adapter/em_http_ssl_patch'
243
+ end if Faraday::Adapter::EMHttp.loaded?
@@ -1,49 +1,43 @@
1
- # frozen_string_literal: true
2
-
3
1
  require 'openssl'
4
2
  require 'em-http'
5
3
 
6
- # EventMachine patch to make SSL work.
7
4
  module EmHttpSslPatch
8
5
  def ssl_verify_peer(cert_string)
6
+ cert = nil
9
7
  begin
10
- @last_seen_cert = OpenSSL::X509::Certificate.new(cert_string)
8
+ cert = OpenSSL::X509::Certificate.new(cert_string)
11
9
  rescue OpenSSL::X509::CertificateError
12
10
  return false
13
11
  end
14
12
 
15
- unless certificate_store.verify(@last_seen_cert)
16
- raise OpenSSL::SSL::SSLError,
17
- %(unable to verify the server certificate for "#{host}")
18
- end
19
-
20
- begin
21
- certificate_store.add_cert(@last_seen_cert)
22
- rescue OpenSSL::X509::StoreError => e
23
- raise e unless e.message == 'cert already in hash table'
13
+ @last_seen_cert = cert
14
+
15
+ if certificate_store.verify(@last_seen_cert)
16
+ begin
17
+ certificate_store.add_cert(@last_seen_cert)
18
+ rescue OpenSSL::X509::StoreError => e
19
+ raise e unless e.message == 'cert already in hash table'
20
+ end
21
+ true
22
+ else
23
+ raise OpenSSL::SSL::SSLError.new(%(unable to verify the server certificate for "#{host}"))
24
24
  end
25
- true
26
25
  end
27
26
 
28
27
  def ssl_handshake_completed
29
28
  return true unless verify_peer?
30
29
 
31
- unless verified_cert_identity?
32
- raise OpenSSL::SSL::SSLError,
33
- %(host "#{host}" does not match the server certificate)
30
+ unless OpenSSL::SSL.verify_certificate_identity(@last_seen_cert, host)
31
+ raise OpenSSL::SSL::SSLError.new(%(host "#{host}" does not match the server certificate))
32
+ else
33
+ true
34
34
  end
35
-
36
- true
37
35
  end
38
36
 
39
37
  def verify_peer?
40
38
  parent.connopts.tls[:verify_peer]
41
39
  end
42
40
 
43
- def verified_cert_identity?
44
- OpenSSL::SSL.verify_certificate_identity(@last_seen_cert, host)
45
- end
46
-
47
41
  def host
48
42
  parent.uri.host
49
43
  end
@@ -1,21 +1,16 @@
1
- # frozen_string_literal: true
2
-
3
1
  module Faraday
4
2
  class Adapter
5
3
  class EMSynchrony < Faraday::Adapter
6
- # A parallel manager for EMSynchrony.
7
4
  class ParallelManager
8
- # Add requests to queue.
9
- #
10
- # @param request [EM::HttpRequest]
11
- # @param method [Symbol, String] HTTP method
12
- # @param args [Array] the rest of the positional arguments
5
+
6
+ # Add requests to queue. The `request` argument should be a
7
+ # `EM::HttpRequest` object.
13
8
  def add(request, method, *args, &block)
14
9
  queue << {
15
- request: request,
16
- method: method,
17
- args: args,
18
- block: block
10
+ :request => request,
11
+ :method => method,
12
+ :args => args,
13
+ :block => block
19
14
  }
20
15
  end
21
16
 
@@ -24,18 +19,19 @@ module Faraday
24
19
  def run
25
20
  result = nil
26
21
  if !EM.reactor_running?
27
- EM.run do
22
+ EM.run {
28
23
  Fiber.new do
29
24
  result = perform
30
25
  EM.stop
31
26
  end.resume
32
- end
27
+ }
33
28
  else
34
29
  result = perform
35
30
  end
36
31
  result
37
32
  end
38
33
 
34
+
39
35
  private
40
36
 
41
37
  # The request queue.
@@ -63,7 +59,8 @@ module Faraday
63
59
  # Block fiber until all requests have returned.
64
60
  multi.perform
65
61
  end
66
- end
67
- end
68
- end
69
- end
62
+
63
+ end # ParallelManager
64
+ end # EMSynchrony
65
+ end # Adapter
66
+ end # Faraday