faraday 1.9.3 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +197 -3
  3. data/LICENSE.md +1 -1
  4. data/README.md +11 -9
  5. data/examples/client_spec.rb +41 -19
  6. data/examples/client_test.rb +48 -22
  7. data/lib/faraday/adapter/test.rb +43 -7
  8. data/lib/faraday/adapter.rb +4 -7
  9. data/lib/faraday/connection.rb +39 -120
  10. data/lib/faraday/encoders/nested_params_encoder.rb +13 -6
  11. data/lib/faraday/error.rb +3 -2
  12. data/lib/faraday/logging/formatter.rb +1 -0
  13. data/lib/faraday/middleware.rb +0 -1
  14. data/lib/faraday/middleware_registry.rb +17 -63
  15. data/lib/faraday/options/env.rb +18 -0
  16. data/lib/faraday/options/ssl_options.rb +11 -1
  17. data/lib/faraday/options.rb +3 -3
  18. data/lib/faraday/rack_builder.rb +23 -20
  19. data/lib/faraday/request/authorization.rb +33 -41
  20. data/lib/faraday/request/instrumentation.rb +2 -0
  21. data/lib/faraday/request/json.rb +55 -0
  22. data/lib/faraday/request/url_encoded.rb +5 -1
  23. data/lib/faraday/request.rb +12 -30
  24. data/lib/faraday/response/json.rb +54 -0
  25. data/lib/faraday/response/logger.rb +4 -4
  26. data/lib/faraday/response/raise_error.rb +9 -1
  27. data/lib/faraday/response.rb +8 -19
  28. data/lib/faraday/utils/headers.rb +1 -1
  29. data/lib/faraday/utils.rb +10 -5
  30. data/lib/faraday/version.rb +1 -1
  31. data/lib/faraday.rb +10 -44
  32. data/spec/faraday/adapter/test_spec.rb +36 -0
  33. data/spec/faraday/connection_spec.rb +148 -91
  34. data/spec/faraday/middleware_registry_spec.rb +31 -0
  35. data/spec/faraday/options/env_spec.rb +8 -2
  36. data/spec/faraday/params_encoders/nested_spec.rb +8 -0
  37. data/spec/faraday/rack_builder_spec.rb +26 -54
  38. data/spec/faraday/request/authorization_spec.rb +50 -28
  39. data/spec/faraday/request/instrumentation_spec.rb +5 -7
  40. data/spec/faraday/request/json_spec.rb +111 -0
  41. data/spec/faraday/request/url_encoded_spec.rb +12 -2
  42. data/spec/faraday/request_spec.rb +5 -15
  43. data/spec/faraday/response/json_spec.rb +117 -0
  44. data/spec/faraday/response/raise_error_spec.rb +7 -4
  45. data/spec/faraday/utils/headers_spec.rb +2 -2
  46. data/spec/faraday/utils_spec.rb +63 -1
  47. data/spec/support/fake_safe_buffer.rb +1 -1
  48. data/spec/support/helper_methods.rb +0 -37
  49. data/spec/support/shared_examples/adapter.rb +2 -2
  50. data/spec/support/shared_examples/request_method.rb +22 -21
  51. metadata +18 -149
  52. data/lib/faraday/adapter/typhoeus.rb +0 -15
  53. data/lib/faraday/autoload.rb +0 -87
  54. data/lib/faraday/dependency_loader.rb +0 -37
  55. data/lib/faraday/request/basic_authentication.rb +0 -20
  56. data/lib/faraday/request/token_authentication.rb +0 -20
  57. data/spec/faraday/adapter/em_http_spec.rb +0 -49
  58. data/spec/faraday/adapter/em_synchrony_spec.rb +0 -18
  59. data/spec/faraday/adapter/excon_spec.rb +0 -49
  60. data/spec/faraday/adapter/httpclient_spec.rb +0 -73
  61. data/spec/faraday/adapter/net_http_spec.rb +0 -64
  62. data/spec/faraday/adapter/patron_spec.rb +0 -18
  63. data/spec/faraday/adapter/rack_spec.rb +0 -8
  64. data/spec/faraday/adapter/typhoeus_spec.rb +0 -7
  65. data/spec/faraday/composite_read_io_spec.rb +0 -80
  66. data/spec/faraday/response/middleware_spec.rb +0 -68
  67. data/spec/support/webmock_rack_app.rb +0 -68
@@ -5,14 +5,9 @@ module Faraday
5
5
  # responsible for fulfilling a Faraday request.
6
6
  class Adapter
7
7
  extend MiddlewareRegistry
8
- extend DependencyLoader
9
8
 
10
9
  CONTENT_LENGTH = 'Content-Length'
11
10
 
12
- register_middleware File.expand_path('adapter', __dir__),
13
- test: [:Test, 'test'],
14
- typhoeus: [:Typhoeus, 'typhoeus']
15
-
16
11
  # This module marks an Adapter as supporting parallel requests.
17
12
  module Parallelism
18
13
  attr_writer :supports_parallel
@@ -64,7 +59,7 @@ module Faraday
64
59
 
65
60
  private
66
61
 
67
- def save_response(env, status, body, headers = nil, reason_phrase = nil)
62
+ def save_response(env, status, body, headers = nil, reason_phrase = nil, finished: true)
68
63
  env.status = status
69
64
  env.body = body
70
65
  env.reason_phrase = reason_phrase&.to_s&.strip
@@ -73,7 +68,7 @@ module Faraday
73
68
  yield(response_headers) if block_given?
74
69
  end
75
70
 
76
- env.response.finish(env) unless env.parallel?
71
+ env.response.finish(env) unless env.parallel? || !finished
77
72
  env.response
78
73
  end
79
74
 
@@ -103,3 +98,5 @@ module Faraday
103
98
  }.freeze
104
99
  end
105
100
  end
101
+
102
+ require 'faraday/adapter/test'
@@ -6,9 +6,9 @@ module Faraday
6
6
  #
7
7
  # @example
8
8
  #
9
- # conn = Faraday::Connection.new 'http://sushi.com'
9
+ # conn = Faraday::Connection.new 'http://httpbingo.org'
10
10
  #
11
- # # GET http://sushi.com/nigiri
11
+ # # GET http://httpbingo.org/nigiri
12
12
  # conn.get 'nigiri'
13
13
  # # => #<Faraday::Response>
14
14
  #
@@ -64,7 +64,7 @@ module Faraday
64
64
  options = ConnectionOptions.from(options)
65
65
 
66
66
  if url.is_a?(Hash) || url.is_a?(ConnectionOptions)
67
- options = options.merge(url)
67
+ options = Utils.deep_merge(options, url)
68
68
  url = options.url
69
69
  end
70
70
 
@@ -117,7 +117,7 @@ module Faraday
117
117
 
118
118
  extend Forwardable
119
119
 
120
- def_delegators :builder, :build, :use, :request, :response, :adapter, :app
120
+ def_delegators :builder, :use, :request, :response, :adapter, :app
121
121
 
122
122
  # Closes the underlying resources and/or connections. In the case of
123
123
  # persistent connections, this closes all currently open connections
@@ -130,10 +130,10 @@ module Faraday
130
130
  # Makes a GET HTTP request without a body.
131
131
  # @!scope class
132
132
  #
133
- # @param url [String] The optional String base URL to use as a prefix for
133
+ # @param url [String, URI, nil] The optional String base URL to use as a prefix for
134
134
  # all requests. Can also be the options Hash.
135
- # @param params [Hash] Hash of URI query unencoded key/value pairs.
136
- # @param headers [Hash] unencoded HTTP header key/value pairs.
135
+ # @param params [Hash, nil] Hash of URI query unencoded key/value pairs.
136
+ # @param headers [Hash, nil] unencoded HTTP header key/value pairs.
137
137
  #
138
138
  # @example
139
139
  # conn.get '/items', { page: 1 }, :accept => 'application/json'
@@ -152,10 +152,10 @@ module Faraday
152
152
  # Makes a HEAD HTTP request without a body.
153
153
  # @!scope class
154
154
  #
155
- # @param url [String] The optional String base URL to use as a prefix for
155
+ # @param url [String, URI, nil] The optional String base URL to use as a prefix for
156
156
  # all requests. Can also be the options Hash.
157
- # @param params [Hash] Hash of URI query unencoded key/value pairs.
158
- # @param headers [Hash] unencoded HTTP header key/value pairs.
157
+ # @param params [Hash, nil] Hash of URI query unencoded key/value pairs.
158
+ # @param headers [Hash, nil] unencoded HTTP header key/value pairs.
159
159
  #
160
160
  # @example
161
161
  # conn.head '/items/1'
@@ -167,10 +167,10 @@ module Faraday
167
167
  # Makes a DELETE HTTP request without a body.
168
168
  # @!scope class
169
169
  #
170
- # @param url [String] The optional String base URL to use as a prefix for
170
+ # @param url [String, URI, nil] The optional String base URL to use as a prefix for
171
171
  # all requests. Can also be the options Hash.
172
- # @param params [Hash] Hash of URI query unencoded key/value pairs.
173
- # @param headers [Hash] unencoded HTTP header key/value pairs.
172
+ # @param params [Hash, nil] Hash of URI query unencoded key/value pairs.
173
+ # @param headers [Hash, nil] unencoded HTTP header key/value pairs.
174
174
  #
175
175
  # @example
176
176
  # conn.delete '/items/1'
@@ -182,10 +182,10 @@ module Faraday
182
182
  # Makes a TRACE HTTP request without a body.
183
183
  # @!scope class
184
184
  #
185
- # @param url [String] The optional String base URL to use as a prefix for
185
+ # @param url [String, URI, nil] The optional String base URL to use as a prefix for
186
186
  # all requests. Can also be the options Hash.
187
- # @param params [Hash] Hash of URI query unencoded key/value pairs.
188
- # @param headers [Hash] unencoded HTTP header key/value pairs.
187
+ # @param params [Hash, nil] Hash of URI query unencoded key/value pairs.
188
+ # @param headers [Hash, nil] unencoded HTTP header key/value pairs.
189
189
  #
190
190
  # @example
191
191
  # conn.connect '/items/1'
@@ -210,9 +210,9 @@ module Faraday
210
210
  #
211
211
  # @overload options(url, params = nil, headers = nil)
212
212
  # Makes an OPTIONS HTTP request to the given URL.
213
- # @param url [String] String base URL to sue as a prefix for all requests.
214
- # @param params [Hash] Hash of URI query unencoded key/value pairs.
215
- # @param headers [Hash] unencoded HTTP header key/value pairs.
213
+ # @param url [String, URI, nil] String base URL to sue as a prefix for all requests.
214
+ # @param params [Hash, nil] Hash of URI query unencoded key/value pairs.
215
+ # @param headers [Hash, nil] unencoded HTTP header key/value pairs.
216
216
  #
217
217
  # @example
218
218
  # conn.options '/items/1'
@@ -233,10 +233,10 @@ module Faraday
233
233
  # Makes a POST HTTP request with a body.
234
234
  # @!scope class
235
235
  #
236
- # @param url [String] The optional String base URL to use as a prefix for
236
+ # @param url [String, URI, nil] The optional String base URL to use as a prefix for
237
237
  # all requests. Can also be the options Hash.
238
- # @param body [String] body for the request.
239
- # @param headers [Hash] unencoded HTTP header key/value pairs.
238
+ # @param body [String, nil] body for the request.
239
+ # @param headers [Hash, nil] unencoded HTTP header key/value pairs.
240
240
  #
241
241
  # @example
242
242
  # conn.post '/items', data, content_type: 'application/json'
@@ -255,10 +255,10 @@ module Faraday
255
255
  # Makes a PUT HTTP request with a body.
256
256
  # @!scope class
257
257
  #
258
- # @param url [String] The optional String base URL to use as a prefix for
258
+ # @param url [String, URI, nil] The optional String base URL to use as a prefix for
259
259
  # all requests. Can also be the options Hash.
260
- # @param body [String] body for the request.
261
- # @param headers [Hash] unencoded HTTP header key/value pairs.
260
+ # @param body [String, nil] body for the request.
261
+ # @param headers [Hash, nil] unencoded HTTP header key/value pairs.
262
262
  #
263
263
  # @example
264
264
  # # TODO: Make it a PUT example
@@ -283,77 +283,6 @@ module Faraday
283
283
  RUBY
284
284
  end
285
285
 
286
- # Sets up the Authorization header with these credentials, encoded
287
- # with base64.
288
- #
289
- # @param login [String] The authentication login.
290
- # @param pass [String] The authentication password.
291
- #
292
- # @example
293
- #
294
- # conn.basic_auth 'Aladdin', 'open sesame'
295
- # conn.headers['Authorization']
296
- # # => "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="
297
- #
298
- # @return [void]
299
- def basic_auth(login, pass)
300
- warn <<~TEXT
301
- WARNING: `Faraday::Connection#basic_auth` is deprecated; it will be removed in version 2.0.
302
- While initializing your connection, use `#request(:basic_auth, ...)` instead.
303
- See https://lostisland.github.io/faraday/middleware/authentication for more usage info.
304
- TEXT
305
- set_authorization_header(:basic_auth, login, pass)
306
- end
307
-
308
- # Sets up the Authorization header with the given token.
309
- #
310
- # @param token [String]
311
- # @param options [Hash] extra token options.
312
- #
313
- # @example
314
- #
315
- # conn.token_auth 'abcdef', foo: 'bar'
316
- # conn.headers['Authorization']
317
- # # => "Token token=\"abcdef\",
318
- # foo=\"bar\""
319
- #
320
- # @return [void]
321
- def token_auth(token, options = nil)
322
- warn <<~TEXT
323
- WARNING: `Faraday::Connection#token_auth` is deprecated; it will be removed in version 2.0.
324
- While initializing your connection, use `#request(:token_auth, ...)` instead.
325
- See https://lostisland.github.io/faraday/middleware/authentication for more usage info.
326
- TEXT
327
- set_authorization_header(:token_auth, token, options)
328
- end
329
-
330
- # Sets up a custom Authorization header.
331
- #
332
- # @param type [String] authorization type
333
- # @param token [String, Hash] token. A String value is taken literally, and
334
- # a Hash is encoded into comma-separated key/value pairs.
335
- #
336
- # @example
337
- #
338
- # conn.authorization :Bearer, 'mF_9.B5f-4.1JqM'
339
- # conn.headers['Authorization']
340
- # # => "Bearer mF_9.B5f-4.1JqM"
341
- #
342
- # conn.authorization :Token, token: 'abcdef', foo: 'bar'
343
- # conn.headers['Authorization']
344
- # # => "Token token=\"abcdef\",
345
- # foo=\"bar\""
346
- #
347
- # @return [void]
348
- def authorization(type, token)
349
- warn <<~TEXT
350
- WARNING: `Faraday::Connection#authorization` is deprecated; it will be removed in version 2.0.
351
- While initializing your connection, use `#request(:authorization, ...)` instead.
352
- See https://lostisland.github.io/faraday/middleware/authentication for more usage info.
353
- TEXT
354
- set_authorization_header(:authorization, type, token)
355
- end
356
-
357
286
  # Check if the adapter is parallel-capable.
358
287
  #
359
288
  # @yield if the adapter isn't parallel-capable, or if no adapter is set yet.
@@ -420,11 +349,11 @@ module Faraday
420
349
  # @example
421
350
  #
422
351
  # conn = Faraday::Connection.new { ... }
423
- # conn.url_prefix = "https://sushi.com/api"
352
+ # conn.url_prefix = "https://httpbingo.org/api"
424
353
  # conn.scheme # => https
425
354
  # conn.path_prefix # => "/api"
426
355
  #
427
- # conn.get("nigiri?page=2") # accesses https://sushi.com/api/nigiri
356
+ # conn.get("nigiri?page=2") # accesses https://httpbingo.org/api/nigiri
428
357
  def url_prefix=(url, encoder = nil)
429
358
  uri = @url_prefix = Utils.URI(url)
430
359
  self.path_prefix = uri.path
@@ -441,7 +370,7 @@ module Faraday
441
370
  end
442
371
 
443
372
  def set_basic_auth(user, password)
444
- header = Faraday::Request::BasicAuthentication.header(user, password)
373
+ header = Faraday::Utils.basic_header_from(user, password)
445
374
  headers[Faraday::Request::Authorization::KEY] = header
446
375
  end
447
376
 
@@ -461,20 +390,20 @@ module Faraday
461
390
  # Takes a relative url for a request and combines it with the defaults
462
391
  # set on the connection instance.
463
392
  #
464
- # @param url [String]
393
+ # @param url [String, URI, nil]
465
394
  # @param extra_params [Hash]
466
395
  #
467
396
  # @example
468
397
  # conn = Faraday::Connection.new { ... }
469
- # conn.url_prefix = "https://sushi.com/api?token=abc"
398
+ # conn.url_prefix = "https://httpbingo.org/api?token=abc"
470
399
  # conn.scheme # => https
471
400
  # conn.path_prefix # => "/api"
472
401
  #
473
402
  # conn.build_url("nigiri?page=2")
474
- # # => https://sushi.com/api/nigiri?token=abc&page=2
403
+ # # => https://httpbingo.org/api/nigiri?token=abc&page=2
475
404
  #
476
405
  # conn.build_url("nigiri", page: 2)
477
- # # => https://sushi.com/api/nigiri?token=abc&page=2
406
+ # # => https://httpbingo.org/api/nigiri?token=abc&page=2
478
407
  #
479
408
  def build_url(url = nil, extra_params = nil)
480
409
  uri = build_exclusive_url(url)
@@ -494,10 +423,10 @@ module Faraday
494
423
  # Builds and runs the Faraday::Request.
495
424
  #
496
425
  # @param method [Symbol] HTTP method.
497
- # @param url [String, URI] String or URI to access.
498
- # @param body [Object] The request body that will eventually be converted to
426
+ # @param url [String, URI, nil] String or URI to access.
427
+ # @param body [String, nil] The request body that will eventually be converted to
499
428
  # a string.
500
- # @param headers [Hash] unencoded HTTP header key/value pairs.
429
+ # @param headers [Hash, nil] unencoded HTTP header key/value pairs.
501
430
  #
502
431
  # @return [Faraday::Response]
503
432
  def run_request(method, url, body, headers)
@@ -533,7 +462,7 @@ module Faraday
533
462
 
534
463
  # Build an absolute URL based on url_prefix.
535
464
  #
536
- # @param url [String, URI]
465
+ # @param url [String, URI, nil]
537
466
  # @param params [Faraday::Utils::ParamsHash] A Faraday::Utils::ParamsHash to
538
467
  # replace the query values
539
468
  # of the resulting url (default: nil).
@@ -545,14 +474,12 @@ module Faraday
545
474
  if url && base.path && base.path !~ %r{/$}
546
475
  base.path = "#{base.path}/" # ensure trailing slash
547
476
  end
548
- url = url && URI.parse(url.to_s).opaque ? url.to_s.gsub(':', '%3A') : url
477
+ url = url.to_s.gsub(':', '%3A') if url && URI.parse(url.to_s).opaque
549
478
  uri = url ? base + url : base
550
479
  if params
551
480
  uri.query = params.to_query(params_encoder || options.params_encoder)
552
481
  end
553
- # rubocop:disable Style/SafeNavigation
554
482
  uri.query = nil if uri.query && uri.query.empty?
555
- # rubocop:enable Style/SafeNavigation
556
483
  uri
557
484
  end
558
485
 
@@ -584,14 +511,6 @@ module Faraday
584
511
  yield(Utils.unescape(uri.user), Utils.unescape(uri.password))
585
512
  end
586
513
 
587
- def set_authorization_header(header_type, *args)
588
- header = Faraday::Request
589
- .lookup_middleware(header_type)
590
- .header(*args)
591
-
592
- headers[Faraday::Request::Authorization::KEY] = header
593
- end
594
-
595
514
  def proxy_from_env(url)
596
515
  return if Faraday.ignore_env_proxy
597
516
 
@@ -618,7 +537,7 @@ module Faraday
618
537
  end
619
538
 
620
539
  def find_default_proxy
621
- uri = ENV['http_proxy']
540
+ uri = ENV.fetch('http_proxy', nil)
622
541
  return unless uri && !uri.empty?
623
542
 
624
543
  uri = "http://#{uri}" unless uri.match?(/^http/i)
@@ -636,7 +555,7 @@ module Faraday
636
555
  end
637
556
 
638
557
  def support_parallel?(adapter)
639
- adapter&.respond_to?(:supports_parallel?) && adapter&.supports_parallel?
558
+ adapter.respond_to?(:supports_parallel?) && adapter&.supports_parallel?
640
559
  end
641
560
  end
642
561
  end
@@ -62,11 +62,17 @@ module Faraday
62
62
  end
63
63
 
64
64
  def encode_array(parent, value)
65
- new_parent = "#{parent}%5B%5D"
66
- return new_parent if value.empty?
65
+ return "#{parent}%5B%5D" if value.empty?
67
66
 
68
67
  buffer = +''
69
- value.each { |val| buffer << "#{encode_pair(new_parent, val)}&" }
68
+ value.each_with_index do |val, index|
69
+ new_parent = if @array_indices
70
+ "#{parent}%5B#{index}%5D"
71
+ else
72
+ "#{parent}%5B%5D"
73
+ end
74
+ buffer << "#{encode_pair(new_parent, val)}&"
75
+ end
70
76
  buffer.chop
71
77
  end
72
78
  end
@@ -102,7 +108,7 @@ module Faraday
102
108
  subkeys = key.scan(SUBKEYS_REGEX)
103
109
  subkeys.each_with_index do |subkey, i|
104
110
  is_array = subkey =~ /[\[\]]+\Z/
105
- subkey = $` if is_array
111
+ subkey = Regexp.last_match.pre_match if is_array
106
112
  last_subkey = i == subkeys.length - 1
107
113
 
108
114
  context = prepare_context(context, subkey, is_array, last_subkey)
@@ -124,7 +130,7 @@ module Faraday
124
130
  value_type = is_array ? Array : Hash
125
131
  if context[subkey] && !context[subkey].is_a?(value_type)
126
132
  raise TypeError, "expected #{value_type.name} " \
127
- "(got #{context[subkey].class.name}) for param `#{subkey}'"
133
+ "(got #{context[subkey].class.name}) for param `#{subkey}'"
128
134
  end
129
135
 
130
136
  context[subkey] ||= value_type.new
@@ -161,7 +167,7 @@ module Faraday
161
167
  # for your requests.
162
168
  module NestedParamsEncoder
163
169
  class << self
164
- attr_accessor :sort_params
170
+ attr_accessor :sort_params, :array_indices
165
171
 
166
172
  extend Forwardable
167
173
  def_delegators :'Faraday::Utils', :escape, :unescape
@@ -169,6 +175,7 @@ module Faraday
169
175
 
170
176
  # Useful default for OAuth and caching.
171
177
  @sort_params = true
178
+ @array_indices = false
172
179
 
173
180
  extend EncodeMethods
174
181
  extend DecodeMethods
data/lib/faraday/error.rb CHANGED
@@ -6,7 +6,7 @@ module Faraday
6
6
  class Error < StandardError
7
7
  attr_reader :response, :wrapped_exception
8
8
 
9
- def initialize(exc, response = nil)
9
+ def initialize(exc = nil, response = nil)
10
10
  @wrapped_exception = nil unless defined?(@wrapped_exception)
11
11
  @response = nil unless defined?(@response)
12
12
  super(exc_msg_and_response!(exc, response))
@@ -52,6 +52,7 @@ module Faraday
52
52
  # :body - Optional string HTTP response body.
53
53
  # :request - Hash
54
54
  # :method - Symbol with the request HTTP method.
55
+ # :url - URI object with the url requested.
55
56
  # :url_path - String with the url path requested.
56
57
  # :params - String key/value hash of query params
57
58
  # present in the request.
@@ -140,7 +141,7 @@ module Faraday
140
141
  class SSLError < Error
141
142
  end
142
143
 
143
- # Raised by FaradayMiddleware::ResponseMiddleware
144
+ # Raised by middlewares that parse the response, like the JSON response middleware.
144
145
  class ParsingError < Error
145
146
  end
146
147
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'pp'
4
+
4
5
  module Faraday
5
6
  module Logging
6
7
  # Serves as an integration point to customize logging
@@ -4,7 +4,6 @@ module Faraday
4
4
  # Middleware is the basic base class of any Faraday middleware.
5
5
  class Middleware
6
6
  extend MiddlewareRegistry
7
- extend DependencyLoader
8
7
 
9
8
  attr_reader :app, :options
10
9
 
@@ -6,59 +6,26 @@ module Faraday
6
6
  # Adds the ability for other modules to register and lookup
7
7
  # middleware classes.
8
8
  module MiddlewareRegistry
9
+ def registered_middleware
10
+ @registered_middleware ||= {}
11
+ end
12
+
9
13
  # Register middleware class(es) on the current module.
10
14
  #
11
- # @param autoload_path [String] Middleware autoload path
12
- # @param mapping [Hash{
13
- # Symbol => Module,
14
- # Symbol => Array<Module, Symbol, String>,
15
- # }] Middleware mapping from a lookup symbol to a reference to the
16
- # middleware.
17
- # Classes can be expressed as:
18
- # - a fully qualified constant
19
- # - a Symbol
20
- # - a Proc that will be lazily called to return the former
21
- # - an array is given, its first element is the constant or symbol,
22
- # and its second is a file to `require`.
15
+ # @param mappings [Hash] Middleware mappings from a lookup symbol to a middleware class.
23
16
  # @return [void]
24
17
  #
25
18
  # @example Lookup by a constant
26
19
  #
27
20
  # module Faraday
28
- # class Whatever
21
+ # class Whatever < Middleware
29
22
  # # Middleware looked up by :foo returns Faraday::Whatever::Foo.
30
- # register_middleware foo: Foo
31
- # end
32
- # end
33
- #
34
- # @example Lookup by a symbol
35
- #
36
- # module Faraday
37
- # class Whatever
38
- # # Middleware looked up by :bar returns
39
- # # Faraday::Whatever.const_get(:Bar)
40
- # register_middleware bar: :Bar
41
- # end
42
- # end
43
- #
44
- # @example Lookup by a symbol and string in an array
45
- #
46
- # module Faraday
47
- # class Whatever
48
- # # Middleware looked up by :baz requires 'baz' and returns
49
- # # Faraday::Whatever.const_get(:Baz)
50
- # register_middleware baz: [:Baz, 'baz']
23
+ # register_middleware(foo: Whatever)
51
24
  # end
52
25
  # end
53
- #
54
- def register_middleware(autoload_path = nil, mapping = nil)
55
- if mapping.nil?
56
- mapping = autoload_path
57
- autoload_path = nil
58
- end
26
+ def register_middleware(**mappings)
59
27
  middleware_mutex do
60
- @middleware_autoload_path = autoload_path if autoload_path
61
- (@registered_middleware ||= {}).update(mapping)
28
+ registered_middleware.update(mappings)
62
29
  end
63
30
  end
64
31
 
@@ -66,7 +33,7 @@ module Faraday
66
33
  #
67
34
  # @param key [Symbol] key for the registered middleware.
68
35
  def unregister_middleware(key)
69
- @registered_middleware.delete(key)
36
+ registered_middleware.delete(key)
70
37
  end
71
38
 
72
39
  # Lookup middleware class with a registered Symbol shortcut.
@@ -78,30 +45,27 @@ module Faraday
78
45
  # @example
79
46
  #
80
47
  # module Faraday
81
- # class Whatever
82
- # register_middleware foo: Foo
48
+ # class Whatever < Middleware
49
+ # register_middleware(foo: Whatever)
83
50
  # end
84
51
  # end
85
52
  #
86
- # Faraday::Whatever.lookup_middleware(:foo)
87
- # # => Faraday::Whatever::Foo
88
- #
53
+ # Faraday::Middleware.lookup_middleware(:foo)
54
+ # # => Faraday::Whatever
89
55
  def lookup_middleware(key)
90
56
  load_middleware(key) ||
91
57
  raise(Faraday::Error, "#{key.inspect} is not registered on #{self}")
92
58
  end
93
59
 
60
+ private
61
+
94
62
  def middleware_mutex(&block)
95
63
  @middleware_mutex ||= Monitor.new
96
64
  @middleware_mutex.synchronize(&block)
97
65
  end
98
66
 
99
- def fetch_middleware(key)
100
- defined?(@registered_middleware) && @registered_middleware[key]
101
- end
102
-
103
67
  def load_middleware(key)
104
- value = fetch_middleware(key)
68
+ value = registered_middleware[key]
105
69
  case value
106
70
  when Module
107
71
  value
@@ -113,16 +77,6 @@ module Faraday
113
77
  middleware_mutex do
114
78
  @registered_middleware[key] = value.call
115
79
  end
116
- when Array
117
- middleware_mutex do
118
- const, path = value
119
- if (root = @middleware_autoload_path)
120
- path = "#{root}/#{path}"
121
- end
122
- require(path)
123
- @registered_middleware[key] = const
124
- end
125
- load_middleware(key)
126
80
  end
127
81
  end
128
82
  end
@@ -157,6 +157,24 @@ module Faraday
157
157
  %(#<#{self.class}#{attrs.join(' ')}>)
158
158
  end
159
159
 
160
+ def stream_response?
161
+ request.stream_response?
162
+ end
163
+
164
+ def stream_response(&block)
165
+ size = 0
166
+ yielded = false
167
+ block_result = block.call do |chunk| # rubocop:disable Performance/RedundantBlockCall
168
+ if chunk.bytesize.positive? || size.positive?
169
+ yielded = true
170
+ size += chunk.bytesize
171
+ request.on_data.call(chunk, size, self)
172
+ end
173
+ end
174
+ request.on_data.call(+'', 0, self) unless yielded
175
+ block_result
176
+ end
177
+
160
178
  # @private
161
179
  def custom_members
162
180
  @custom_members ||= {}
@@ -6,6 +6,10 @@ module Faraday
6
6
  # @!attribute verify
7
7
  # @return [Boolean] whether to verify SSL certificates or not
8
8
  #
9
+ # @!attribute verify_hostname
10
+ # @return [Boolean] whether to enable hostname verification on server certificates
11
+ # during the handshake or not (see https://github.com/ruby/openssl/pull/60)
12
+ #
9
13
  # @!attribute ca_file
10
14
  # @return [String] CA file
11
15
  #
@@ -41,7 +45,8 @@ module Faraday
41
45
  #
42
46
  # @!attribute max_version
43
47
  # @return [String, Symbol] maximum SSL version (see https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html#method-i-max_version-3D)
44
- class SSLOptions < Options.new(:verify, :ca_file, :ca_path, :verify_mode,
48
+ class SSLOptions < Options.new(:verify, :verify_hostname,
49
+ :ca_file, :ca_path, :verify_mode,
45
50
  :cert_store, :client_cert, :client_key,
46
51
  :certificate, :private_key, :verify_depth,
47
52
  :version, :min_version, :max_version)
@@ -55,5 +60,10 @@ module Faraday
55
60
  def disable?
56
61
  !verify?
57
62
  end
63
+
64
+ # @return [Boolean] true if should verify_hostname
65
+ def verify_hostname?
66
+ verify_hostname != false
67
+ end
58
68
  end
59
69
  end
@@ -104,7 +104,7 @@ module Faraday
104
104
 
105
105
  # Public
106
106
  def each_key(&block)
107
- return to_enum(:each_key) unless block_given?
107
+ return to_enum(:each_key) unless block
108
108
 
109
109
  keys.each(&block)
110
110
  end
@@ -118,7 +118,7 @@ module Faraday
118
118
 
119
119
  # Public
120
120
  def each_value(&block)
121
- return to_enum(:each_value) unless block_given?
121
+ return to_enum(:each_value) unless block
122
122
 
123
123
  values.each(&block)
124
124
  end
@@ -168,7 +168,7 @@ module Faraday
168
168
  end
169
169
 
170
170
  def self.memoized(key, &block)
171
- unless block_given?
171
+ unless block
172
172
  raise ArgumentError, '#memoized must be called with a block'
173
173
  end
174
174