faraday 0.17.3 → 2.7.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +350 -8
  3. data/LICENSE.md +1 -1
  4. data/README.md +27 -367
  5. data/Rakefile +1 -7
  6. data/examples/client_spec.rb +119 -0
  7. data/examples/client_test.rb +144 -0
  8. data/lib/faraday/adapter/test.rb +170 -72
  9. data/lib/faraday/adapter.rb +69 -23
  10. data/lib/faraday/adapter_registry.rb +30 -0
  11. data/lib/faraday/connection.rb +309 -233
  12. data/lib/faraday/encoders/flat_params_encoder.rb +105 -0
  13. data/lib/faraday/encoders/nested_params_encoder.rb +183 -0
  14. data/lib/faraday/error.rb +31 -42
  15. data/lib/faraday/logging/formatter.rb +122 -0
  16. data/lib/faraday/methods.rb +6 -0
  17. data/lib/faraday/middleware.rb +21 -25
  18. data/lib/faraday/middleware_registry.rb +83 -0
  19. data/lib/faraday/options/connection_options.rb +22 -0
  20. data/lib/faraday/options/env.rb +205 -0
  21. data/lib/faraday/options/proxy_options.rb +32 -0
  22. data/lib/faraday/options/request_options.rb +22 -0
  23. data/lib/faraday/options/ssl_options.rb +69 -0
  24. data/lib/faraday/options.rb +38 -193
  25. data/lib/faraday/parameters.rb +4 -197
  26. data/lib/faraday/rack_builder.rb +91 -76
  27. data/lib/faraday/request/authorization.rb +42 -29
  28. data/lib/faraday/request/instrumentation.rb +47 -27
  29. data/lib/faraday/request/json.rb +55 -0
  30. data/lib/faraday/request/url_encoded.rb +48 -24
  31. data/lib/faraday/request.rb +64 -42
  32. data/lib/faraday/response/json.rb +54 -0
  33. data/lib/faraday/response/logger.rb +24 -67
  34. data/lib/faraday/response/raise_error.rb +57 -18
  35. data/lib/faraday/response.rb +26 -32
  36. data/lib/faraday/utils/headers.rb +144 -0
  37. data/lib/faraday/utils/params_hash.rb +61 -0
  38. data/lib/faraday/utils.rb +47 -251
  39. data/lib/faraday/version.rb +5 -0
  40. data/lib/faraday.rb +108 -198
  41. data/spec/external_adapters/faraday_specs_setup.rb +14 -0
  42. data/spec/faraday/adapter/test_spec.rb +442 -0
  43. data/spec/faraday/adapter_registry_spec.rb +28 -0
  44. data/spec/faraday/adapter_spec.rb +55 -0
  45. data/spec/faraday/connection_spec.rb +808 -0
  46. data/spec/faraday/error_spec.rb +12 -54
  47. data/spec/faraday/middleware_registry_spec.rb +31 -0
  48. data/spec/faraday/middleware_spec.rb +70 -0
  49. data/spec/faraday/options/env_spec.rb +76 -0
  50. data/spec/faraday/options/options_spec.rb +297 -0
  51. data/spec/faraday/options/proxy_options_spec.rb +44 -0
  52. data/spec/faraday/options/request_options_spec.rb +19 -0
  53. data/spec/faraday/params_encoders/flat_spec.rb +42 -0
  54. data/spec/faraday/params_encoders/nested_spec.rb +150 -0
  55. data/spec/faraday/rack_builder_spec.rb +317 -0
  56. data/spec/faraday/request/authorization_spec.rb +118 -0
  57. data/spec/faraday/request/instrumentation_spec.rb +74 -0
  58. data/spec/faraday/request/json_spec.rb +111 -0
  59. data/spec/faraday/request/url_encoded_spec.rb +93 -0
  60. data/spec/faraday/request_spec.rb +110 -0
  61. data/spec/faraday/response/json_spec.rb +117 -0
  62. data/spec/faraday/response/logger_spec.rb +248 -0
  63. data/spec/faraday/response/raise_error_spec.rb +81 -15
  64. data/spec/faraday/response_spec.rb +77 -0
  65. data/spec/faraday/utils/headers_spec.rb +100 -0
  66. data/spec/faraday/utils_spec.rb +118 -0
  67. data/spec/faraday_spec.rb +37 -0
  68. data/spec/spec_helper.rb +63 -36
  69. data/spec/support/disabling_stub.rb +14 -0
  70. data/spec/support/fake_safe_buffer.rb +15 -0
  71. data/spec/support/helper_methods.rb +96 -0
  72. data/spec/support/shared_examples/adapter.rb +105 -0
  73. data/spec/support/shared_examples/params_encoder.rb +18 -0
  74. data/spec/support/shared_examples/request_method.rb +263 -0
  75. data/spec/support/streaming_response_checker.rb +35 -0
  76. metadata +76 -59
  77. data/lib/faraday/adapter/em_http.rb +0 -243
  78. data/lib/faraday/adapter/em_http_ssl_patch.rb +0 -56
  79. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +0 -66
  80. data/lib/faraday/adapter/em_synchrony.rb +0 -106
  81. data/lib/faraday/adapter/excon.rb +0 -82
  82. data/lib/faraday/adapter/httpclient.rb +0 -128
  83. data/lib/faraday/adapter/net_http.rb +0 -152
  84. data/lib/faraday/adapter/net_http_persistent.rb +0 -68
  85. data/lib/faraday/adapter/patron.rb +0 -95
  86. data/lib/faraday/adapter/rack.rb +0 -58
  87. data/lib/faraday/adapter/typhoeus.rb +0 -12
  88. data/lib/faraday/autoload.rb +0 -84
  89. data/lib/faraday/deprecate.rb +0 -107
  90. data/lib/faraday/request/basic_authentication.rb +0 -13
  91. data/lib/faraday/request/multipart.rb +0 -68
  92. data/lib/faraday/request/retry.rb +0 -213
  93. data/lib/faraday/request/token_authentication.rb +0 -15
  94. data/lib/faraday/upload_io.rb +0 -67
  95. data/spec/faraday/deprecate_spec.rb +0 -69
  96. data/test/adapters/default_test.rb +0 -14
  97. data/test/adapters/em_http_test.rb +0 -30
  98. data/test/adapters/em_synchrony_test.rb +0 -32
  99. data/test/adapters/excon_test.rb +0 -30
  100. data/test/adapters/httpclient_test.rb +0 -34
  101. data/test/adapters/integration.rb +0 -263
  102. data/test/adapters/logger_test.rb +0 -136
  103. data/test/adapters/net_http_persistent_test.rb +0 -114
  104. data/test/adapters/net_http_test.rb +0 -79
  105. data/test/adapters/patron_test.rb +0 -40
  106. data/test/adapters/rack_test.rb +0 -38
  107. data/test/adapters/test_middleware_test.rb +0 -157
  108. data/test/adapters/typhoeus_test.rb +0 -38
  109. data/test/authentication_middleware_test.rb +0 -65
  110. data/test/composite_read_io_test.rb +0 -109
  111. data/test/connection_test.rb +0 -738
  112. data/test/env_test.rb +0 -268
  113. data/test/helper.rb +0 -75
  114. data/test/live_server.rb +0 -67
  115. data/test/middleware/instrumentation_test.rb +0 -88
  116. data/test/middleware/retry_test.rb +0 -282
  117. data/test/middleware_stack_test.rb +0 -260
  118. data/test/multibyte.txt +0 -1
  119. data/test/options_test.rb +0 -333
  120. data/test/parameters_test.rb +0 -157
  121. data/test/request_middleware_test.rb +0 -126
  122. data/test/response_middleware_test.rb +0 -72
  123. data/test/strawberry.rb +0 -2
  124. data/test/utils_test.rb +0 -98
@@ -1,51 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'timeout'
4
+
1
5
  module Faraday
2
6
  class Adapter
3
- # Examples
4
- #
7
+ # @example
5
8
  # test = Faraday::Connection.new do
6
9
  # use Faraday::Adapter::Test do |stub|
7
- # # simply define matcher to match the request
10
+ # # Define matcher to match the request
8
11
  # stub.get '/resource.json' do
9
12
  # # return static content
10
13
  # [200, {'Content-Type' => 'application/json'}, 'hi world']
11
14
  # end
12
- #
15
+ #
13
16
  # # response with content generated based on request
14
17
  # stub.get '/showget' do |env|
15
18
  # [200, {'Content-Type' => 'text/plain'}, env[:method].to_s]
16
19
  # end
17
- #
18
- # # regular expression can be used as matching filter
20
+ #
21
+ # # A regular expression can be used as matching filter
19
22
  # stub.get /\A\/items\/(\d+)\z/ do |env, meta|
20
- # # in case regular expression is used an instance of MatchData can be received
21
- # [200, {'Content-Type' => 'text/plain'}, "showing item: #{meta[:match_data][1]}"]
23
+ # # in case regular expression is used, an instance of MatchData
24
+ # # can be received
25
+ # [200,
26
+ # {'Content-Type' => 'text/plain'},
27
+ # "showing item: #{meta[:match_data][1]}"
28
+ # ]
22
29
  # end
30
+ #
31
+ # # Test the request body is the same as the stubbed body
32
+ # stub.post('/bar', 'name=YK&word=call') { [200, {}, ''] }
33
+ #
34
+ # # You can pass a proc as a stubbed body and check the request body in your way.
35
+ # # In this case, the proc should return true or false.
36
+ # stub.post('/foo', ->(request_body) do
37
+ # JSON.parse(request_body).slice('name') == { 'name' => 'YK' } }) { [200, {}, '']
38
+ # end
39
+ #
40
+ # # You can set strict_mode to exactly match the stubbed requests.
41
+ # stub.strict_mode = true
23
42
  # end
24
43
  # end
25
- #
44
+ #
26
45
  # resp = test.get '/resource.json'
27
46
  # resp.body # => 'hi world'
28
- #
47
+ #
29
48
  # resp = test.get '/showget'
30
49
  # resp.body # => 'get'
31
- #
50
+ #
32
51
  # resp = test.get '/items/1'
33
52
  # resp.body # => 'showing item: 1'
34
- #
53
+ #
35
54
  # resp = test.get '/items/2'
36
55
  # resp.body # => 'showing item: 2'
37
56
  #
38
-
57
+ # resp = test.post '/bar', 'name=YK&word=call'
58
+ # resp.status # => 200
59
+ #
60
+ # resp = test.post '/foo', JSON.dump(name: 'YK', created_at: Time.now)
61
+ # resp.status # => 200
39
62
  class Test < Faraday::Adapter
40
63
  attr_accessor :stubs
41
64
 
65
+ # A stack of Stubs
42
66
  class Stubs
43
67
  class NotFound < StandardError
44
68
  end
45
69
 
46
- def initialize
47
- # {:get => [Stub, Stub]}
48
- @stack, @consumed = {}, {}
70
+ def initialize(strict_mode: false)
71
+ # { get: [Stub, Stub] }
72
+ @stack = {}
73
+ @consumed = {}
74
+ @strict_mode = strict_mode
75
+ @stubs_mutex = Monitor.new
49
76
  yield(self) if block_given?
50
77
  end
51
78
 
@@ -53,17 +80,23 @@ module Faraday
53
80
  @stack.empty?
54
81
  end
55
82
 
56
- def match(request_method, host, path, headers, body)
57
- return false if !@stack.key?(request_method)
83
+ # @param env [Faraday::Env]
84
+ def match(env)
85
+ request_method = env[:method]
86
+ return false unless @stack.key?(request_method)
87
+
58
88
  stack = @stack[request_method]
59
89
  consumed = (@consumed[request_method] ||= [])
60
90
 
61
- stub, meta = matches?(stack, host, path, headers, body)
62
- if stub
63
- consumed << stack.delete(stub)
64
- return stub, meta
91
+ @stubs_mutex.synchronize do
92
+ stub, meta = matches?(stack, env)
93
+ if stub
94
+ removed = stack.delete(stub)
95
+ consumed << removed unless removed.nil?
96
+ return stub, meta
97
+ end
65
98
  end
66
- matches?(consumed, host, path, headers, body)
99
+ matches?(consumed, env)
67
100
  end
68
101
 
69
102
  def get(path, headers = {}, &block)
@@ -74,15 +107,15 @@ module Faraday
74
107
  new_stub(:head, path, headers, &block)
75
108
  end
76
109
 
77
- def post(path, body=nil, headers = {}, &block)
110
+ def post(path, body = nil, headers = {}, &block)
78
111
  new_stub(:post, path, headers, body, &block)
79
112
  end
80
113
 
81
- def put(path, body=nil, headers = {}, &block)
114
+ def put(path, body = nil, headers = {}, &block)
82
115
  new_stub(:put, path, headers, body, &block)
83
116
  end
84
117
 
85
- def patch(path, body=nil, headers = {}, &block)
118
+ def patch(path, body = nil, headers = {}, &block)
86
119
  new_stub(:patch, path, headers, body, &block)
87
120
  end
88
121
 
@@ -98,87 +131,131 @@ module Faraday
98
131
  def verify_stubbed_calls
99
132
  failed_stubs = []
100
133
  @stack.each do |method, stubs|
101
- unless stubs.size == 0
102
- failed_stubs.concat(stubs.map {|stub|
134
+ next if stubs.empty?
135
+
136
+ failed_stubs.concat(
137
+ stubs.map do |stub|
103
138
  "Expected #{method} #{stub}."
104
- })
139
+ end
140
+ )
141
+ end
142
+ raise failed_stubs.join(' ') unless failed_stubs.empty?
143
+ end
144
+
145
+ # Set strict_mode. If the value is true, this adapter tries to find matched requests strictly,
146
+ # which means that all of a path, parameters, and headers must be the same as an actual request.
147
+ def strict_mode=(value)
148
+ @strict_mode = value
149
+ @stack.each do |_method, stubs|
150
+ stubs.each do |stub|
151
+ stub.strict_mode = value
105
152
  end
106
153
  end
107
- raise failed_stubs.join(" ") unless failed_stubs.size == 0
108
154
  end
109
155
 
110
156
  protected
111
157
 
112
- def new_stub(request_method, path, headers = {}, body=nil, &block)
158
+ def new_stub(request_method, path, headers = {}, body = nil, &block)
113
159
  normalized_path, host =
114
160
  if path.is_a?(Regexp)
115
161
  path
116
162
  else
117
- [Faraday::Utils.normalize_path(path), Faraday::Utils.URI(path).host]
163
+ [
164
+ Faraday::Utils.normalize_path(path),
165
+ Faraday::Utils.URI(path).host
166
+ ]
118
167
  end
168
+ path, query = normalized_path.respond_to?(:split) ? normalized_path.split('?') : normalized_path
169
+ headers = Utils::Headers.new(headers)
119
170
 
120
- (@stack[request_method] ||= []) << Stub.new(host, normalized_path, headers, body, block)
171
+ stub = Stub.new(host, path, query, headers, body, @strict_mode, block)
172
+ (@stack[request_method] ||= []) << stub
121
173
  end
122
174
 
123
- def matches?(stack, host, path, headers, body)
175
+ # @param stack [Hash]
176
+ # @param env [Faraday::Env]
177
+ def matches?(stack, env)
124
178
  stack.each do |stub|
125
- match_result, meta = stub.matches?(host, path, headers, body)
179
+ match_result, meta = stub.matches?(env)
126
180
  return stub, meta if match_result
127
181
  end
128
182
  nil
129
183
  end
130
184
  end
131
185
 
132
- class Stub < Struct.new(:host, :path, :params, :headers, :body, :block)
133
- def initialize(host, full, headers, body, block)
134
- path, query = full.respond_to?(:split) ? full.split("?") : full
135
- params = query ?
136
- Faraday::Utils.parse_nested_query(query) :
137
- {}
138
- super(host, path, params, headers, body, block)
139
- end
140
-
141
- def matches?(request_host, request_uri, request_headers, request_body)
142
- request_path, request_query = request_uri.split('?')
143
- request_params = request_query ?
144
- Faraday::Utils.parse_nested_query(request_query) :
145
- {}
146
- # meta is a hash use as carrier
186
+ # Stub request
187
+ class Stub < Struct.new(:host, :path, :query, :headers, :body, :strict_mode, :block) # rubocop:disable Style/StructInheritance
188
+ # @param env [Faraday::Env]
189
+ def matches?(env)
190
+ request_host = env[:url].host
191
+ request_path = Faraday::Utils.normalize_path(env[:url].path)
192
+ request_headers = env.request_headers
193
+ request_body = env[:body]
194
+
195
+ # meta is a hash used as carrier
147
196
  # that will be yielded to consumer block
148
197
  meta = {}
149
- return (host.nil? || host == request_host) &&
198
+ [(host.nil? || host == request_host) &&
150
199
  path_match?(request_path, meta) &&
151
- params_match?(request_params) &&
152
- (body.to_s.size.zero? || request_body == body) &&
153
- headers_match?(request_headers), meta
200
+ params_match?(env) &&
201
+ body_match?(request_body) &&
202
+ headers_match?(request_headers), meta]
154
203
  end
155
204
 
156
205
  def path_match?(request_path, meta)
157
- if path.is_a? Regexp
206
+ if path.is_a?(Regexp)
158
207
  !!(meta[:match_data] = path.match(request_path))
159
208
  else
160
209
  path == request_path
161
210
  end
162
211
  end
163
212
 
164
- def params_match?(request_params)
213
+ # @param env [Faraday::Env]
214
+ def params_match?(env)
215
+ request_params = env[:params]
216
+ params = env.params_encoder.decode(query) || {}
217
+
218
+ if strict_mode
219
+ return Set.new(params) == Set.new(request_params)
220
+ end
221
+
165
222
  params.keys.all? do |key|
166
223
  request_params[key] == params[key]
167
224
  end
168
225
  end
169
226
 
170
227
  def headers_match?(request_headers)
228
+ if strict_mode
229
+ headers_with_user_agent = headers.dup.tap do |hs|
230
+ # NOTE: Set User-Agent in case it's not set when creating Stubs.
231
+ # Users would not want to set Faraday's User-Agent explicitly.
232
+ hs[:user_agent] ||= Connection::USER_AGENT
233
+ end
234
+ return Set.new(headers_with_user_agent) == Set.new(request_headers)
235
+ end
236
+
171
237
  headers.keys.all? do |key|
172
238
  request_headers[key] == headers[key]
173
239
  end
174
240
  end
175
241
 
242
+ def body_match?(request_body)
243
+ return true if body.to_s.empty?
244
+
245
+ case body
246
+ when Proc
247
+ body.call(request_body)
248
+ else
249
+ request_body == body
250
+ end
251
+ end
252
+
176
253
  def to_s
177
254
  "#{path} #{body}"
178
255
  end
179
256
  end
180
257
 
181
- def initialize(app, stubs=nil, &block)
258
+ def initialize(app, stubs = nil, &block)
182
259
  super(app)
183
260
  @stubs = stubs || Stubs.new
184
261
  configure(&block) if block
@@ -188,26 +265,47 @@ module Faraday
188
265
  yield(stubs)
189
266
  end
190
267
 
268
+ # @param env [Faraday::Env]
191
269
  def call(env)
192
270
  super
193
- host = env[:url].host
194
- normalized_path = Faraday::Utils.normalize_path(env[:url])
195
- params_encoder = env.request.params_encoder || Faraday::Utils.default_params_encoder
196
-
197
- stub, meta = stubs.match(env[:method], host, normalized_path, env.request_headers, env[:body])
198
- if stub
199
- env[:params] = (query = env[:url].query) ?
200
- params_encoder.decode(query) : {}
201
- block_arity = stub.block.arity
202
- status, headers, body = (block_arity >= 0) ?
203
- stub.block.call(*[env, meta].take(block_arity)) :
204
- stub.block.call(env, meta)
205
- save_response(env, status, body, headers)
206
- else
207
- raise Stubs::NotFound, "no stubbed request for #{env[:method]} #{normalized_path} #{env[:body]}"
271
+
272
+ env.request.params_encoder ||= Faraday::Utils.default_params_encoder
273
+ env[:params] = env.params_encoder.decode(env[:url].query) || {}
274
+ stub, meta = stubs.match(env)
275
+
276
+ unless stub
277
+ raise Stubs::NotFound, "no stubbed request for #{env[:method]} " \
278
+ "#{env[:url]} #{env[:body]}"
208
279
  end
280
+
281
+ block_arity = stub.block.arity
282
+ params = if block_arity >= 0
283
+ [env, meta].take(block_arity)
284
+ else
285
+ [env, meta]
286
+ end
287
+
288
+ timeout = request_timeout(:open, env[:request])
289
+ timeout ||= request_timeout(:read, env[:request])
290
+
291
+ status, headers, body =
292
+ if timeout
293
+ ::Timeout.timeout(timeout, Faraday::TimeoutError) do
294
+ stub.block.call(*params)
295
+ end
296
+ else
297
+ stub.block.call(*params)
298
+ end
299
+
300
+ # We need to explicitly pass `reason_phrase = nil` here to avoid keyword args conflicts.
301
+ # See https://github.com/lostisland/faraday/issues/1444
302
+ # TODO: remove `nil` explicit reason_phrase once Ruby 3.0 becomes minimum req. version
303
+ save_response(env, status, body, headers, nil)
304
+
209
305
  @app.call(env)
210
306
  end
211
307
  end
212
308
  end
213
309
  end
310
+
311
+ Faraday::Adapter.register_middleware(test: Faraday::Adapter::Test)
@@ -1,55 +1,101 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Faraday
2
- # Public: This is a base class for all Faraday adapters. Adapters are
4
+ # Base class for all Faraday adapters. Adapters are
3
5
  # responsible for fulfilling a Faraday request.
4
- class Adapter < Middleware
5
- CONTENT_LENGTH = 'Content-Length'.freeze
6
-
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.
6
+ class Adapter
7
+ extend MiddlewareRegistry
8
+
9
+ CONTENT_LENGTH = 'Content-Length'
10
+
11
+ # This module marks an Adapter as supporting parallel requests.
20
12
  module Parallelism
21
13
  attr_writer :supports_parallel
22
- def supports_parallel?() @supports_parallel end
14
+
15
+ def supports_parallel?
16
+ @supports_parallel
17
+ end
23
18
 
24
19
  def inherited(subclass)
25
20
  super
26
- subclass.supports_parallel = self.supports_parallel?
21
+ subclass.supports_parallel = supports_parallel?
27
22
  end
28
23
  end
29
24
 
30
25
  extend Parallelism
31
26
  self.supports_parallel = false
32
27
 
33
- def initialize(app = nil, opts = {}, &block)
34
- super(app)
28
+ def initialize(_app = nil, opts = {}, &block)
29
+ @app = ->(env) { env.response }
35
30
  @connection_options = opts
36
31
  @config_block = block
37
32
  end
38
33
 
34
+ # Yields or returns an adapter's configured connection. Depends on
35
+ # #build_connection being defined on this adapter.
36
+ #
37
+ # @param env [Faraday::Env, Hash] The env object for a faraday request.
38
+ #
39
+ # @return The return value of the given block, or the HTTP connection object
40
+ # if no block is given.
41
+ def connection(env)
42
+ conn = build_connection(env)
43
+ return conn unless block_given?
44
+
45
+ yield conn
46
+ end
47
+
48
+ # Close any persistent connections. The adapter should still be usable
49
+ # after calling close.
50
+ def close
51
+ # Possible implementation:
52
+ # @app.close if @app.respond_to?(:close)
53
+ end
54
+
39
55
  def call(env)
40
56
  env.clear_body if env.needs_body?
57
+ env.response = Response.new
41
58
  end
42
59
 
43
60
  private
44
61
 
45
- 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)
46
63
  env.status = status
47
64
  env.body = body
48
- env.reason_phrase = reason_phrase && reason_phrase.to_s.strip
65
+ env.reason_phrase = reason_phrase&.to_s&.strip
49
66
  env.response_headers = Utils::Headers.new.tap do |response_headers|
50
67
  response_headers.update headers unless headers.nil?
51
68
  yield(response_headers) if block_given?
52
69
  end
70
+
71
+ env.response.finish(env) unless env.parallel? || !finished
72
+ env.response
73
+ end
74
+
75
+ # Fetches either a read, write, or open timeout setting. Defaults to the
76
+ # :timeout value if a more specific one is not given.
77
+ #
78
+ # @param type [Symbol] Describes which timeout setting to get: :read,
79
+ # :write, or :open.
80
+ # @param options [Hash] Hash containing Symbol keys like :timeout,
81
+ # :read_timeout, :write_timeout, or :open_timeout
82
+ #
83
+ # @return [Integer, nil] Timeout duration in seconds, or nil if no timeout
84
+ # has been set.
85
+ def request_timeout(type, options)
86
+ key = TIMEOUT_KEYS.fetch(type) do
87
+ msg = "Expected :read, :write, :open. Got #{type.inspect} :("
88
+ raise ArgumentError, msg
89
+ end
90
+ options[key] || options[:timeout]
53
91
  end
92
+
93
+ TIMEOUT_KEYS = {
94
+ read: :read_timeout,
95
+ open: :open_timeout,
96
+ write: :write_timeout
97
+ }.freeze
54
98
  end
55
99
  end
100
+
101
+ require 'faraday/adapter/test'
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'monitor'
4
+
5
+ module Faraday
6
+ # AdapterRegistry registers adapter class names so they can be looked up by a
7
+ # String or Symbol name.
8
+ class AdapterRegistry
9
+ def initialize
10
+ @lock = Monitor.new
11
+ @constants = {}
12
+ end
13
+
14
+ def get(name)
15
+ klass = @lock.synchronize do
16
+ @constants[name]
17
+ end
18
+ return klass if klass
19
+
20
+ Object.const_get(name).tap { |c| set(c, name) }
21
+ end
22
+
23
+ def set(klass, name = nil)
24
+ name ||= klass.to_s
25
+ @lock.synchronize do
26
+ @constants[name] = klass
27
+ end
28
+ end
29
+ end
30
+ end