faraday 0.9.1 → 2.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +554 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +32 -197
  5. data/Rakefile +4 -68
  6. data/examples/client_spec.rb +119 -0
  7. data/examples/client_test.rb +144 -0
  8. data/lib/faraday/adapter/test.rb +194 -58
  9. data/lib/faraday/adapter.rb +76 -20
  10. data/lib/faraday/adapter_registry.rb +30 -0
  11. data/lib/faraday/connection.rb +341 -212
  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 +123 -29
  15. data/lib/faraday/logging/formatter.rb +106 -0
  16. data/lib/faraday/methods.rb +6 -0
  17. data/lib/faraday/middleware.rb +18 -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 +199 -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 +63 -195
  25. data/lib/faraday/parameters.rb +4 -180
  26. data/lib/faraday/rack_builder.rb +99 -59
  27. data/lib/faraday/request/authorization.rb +37 -30
  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 +76 -32
  32. data/lib/faraday/response/json.rb +54 -0
  33. data/lib/faraday/response/logger.rb +22 -48
  34. data/lib/faraday/response/raise_error.rb +57 -14
  35. data/lib/faraday/response.rb +32 -35
  36. data/lib/faraday/utils/headers.rb +139 -0
  37. data/lib/faraday/utils/params_hash.rb +61 -0
  38. data/lib/faraday/utils.rb +47 -222
  39. data/lib/faraday/version.rb +5 -0
  40. data/lib/faraday.rb +111 -222
  41. data/spec/external_adapters/faraday_specs_setup.rb +14 -0
  42. data/spec/faraday/adapter/test_spec.rb +413 -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 +793 -0
  46. data/spec/faraday/error_spec.rb +60 -0
  47. data/spec/faraday/middleware_registry_spec.rb +31 -0
  48. data/spec/faraday/middleware_spec.rb +52 -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 +83 -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 +220 -0
  63. data/spec/faraday/response/raise_error_spec.rb +172 -0
  64. data/spec/faraday/response_spec.rb +75 -0
  65. data/spec/faraday/utils/headers_spec.rb +82 -0
  66. data/spec/faraday/utils_spec.rb +118 -0
  67. data/spec/faraday_spec.rb +37 -0
  68. data/spec/spec_helper.rb +132 -0
  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 +81 -109
  77. data/.document +0 -6
  78. data/CONTRIBUTING.md +0 -36
  79. data/Gemfile +0 -25
  80. data/faraday.gemspec +0 -34
  81. data/lib/faraday/adapter/em_http.rb +0 -237
  82. data/lib/faraday/adapter/em_http_ssl_patch.rb +0 -56
  83. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +0 -66
  84. data/lib/faraday/adapter/em_synchrony.rb +0 -92
  85. data/lib/faraday/adapter/excon.rb +0 -80
  86. data/lib/faraday/adapter/httpclient.rb +0 -106
  87. data/lib/faraday/adapter/net_http.rb +0 -130
  88. data/lib/faraday/adapter/net_http_persistent.rb +0 -48
  89. data/lib/faraday/adapter/patron.rb +0 -72
  90. data/lib/faraday/adapter/rack.rb +0 -58
  91. data/lib/faraday/adapter/typhoeus.rb +0 -123
  92. data/lib/faraday/autoload.rb +0 -84
  93. data/lib/faraday/request/basic_authentication.rb +0 -13
  94. data/lib/faraday/request/multipart.rb +0 -63
  95. data/lib/faraday/request/retry.rb +0 -148
  96. data/lib/faraday/request/token_authentication.rb +0 -15
  97. data/lib/faraday/upload_io.rb +0 -67
  98. data/script/cached-bundle +0 -46
  99. data/script/console +0 -7
  100. data/script/generate_certs +0 -42
  101. data/script/package +0 -7
  102. data/script/proxy-server +0 -42
  103. data/script/release +0 -17
  104. data/script/s3-put +0 -71
  105. data/script/server +0 -36
  106. data/script/test +0 -172
  107. data/test/adapters/default_test.rb +0 -14
  108. data/test/adapters/em_http_test.rb +0 -20
  109. data/test/adapters/em_synchrony_test.rb +0 -20
  110. data/test/adapters/excon_test.rb +0 -20
  111. data/test/adapters/httpclient_test.rb +0 -21
  112. data/test/adapters/integration.rb +0 -254
  113. data/test/adapters/logger_test.rb +0 -82
  114. data/test/adapters/net_http_persistent_test.rb +0 -20
  115. data/test/adapters/net_http_test.rb +0 -14
  116. data/test/adapters/patron_test.rb +0 -20
  117. data/test/adapters/rack_test.rb +0 -31
  118. data/test/adapters/test_middleware_test.rb +0 -114
  119. data/test/adapters/typhoeus_test.rb +0 -28
  120. data/test/authentication_middleware_test.rb +0 -65
  121. data/test/composite_read_io_test.rb +0 -111
  122. data/test/connection_test.rb +0 -522
  123. data/test/env_test.rb +0 -218
  124. data/test/helper.rb +0 -81
  125. data/test/live_server.rb +0 -67
  126. data/test/middleware/instrumentation_test.rb +0 -88
  127. data/test/middleware/retry_test.rb +0 -177
  128. data/test/middleware_stack_test.rb +0 -173
  129. data/test/multibyte.txt +0 -1
  130. data/test/options_test.rb +0 -252
  131. data/test/parameters_test.rb +0 -64
  132. data/test/request_middleware_test.rb +0 -142
  133. data/test/response_middleware_test.rb +0 -72
  134. data/test/strawberry.rb +0 -2
  135. data/test/utils_test.rb +0 -58
@@ -1,26 +1,76 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Faraday
2
4
  class Adapter
3
- # test = Faraday::Connection.new do
4
- # use Faraday::Adapter::Test do |stub|
5
- # stub.get '/nigiri/sake.json' do
6
- # [200, {}, 'hi world']
5
+ # @example
6
+ # test = Faraday::Connection.new do
7
+ # use Faraday::Adapter::Test do |stub|
8
+ # # Define matcher to match the request
9
+ # stub.get '/resource.json' do
10
+ # # return static content
11
+ # [200, {'Content-Type' => 'application/json'}, 'hi world']
12
+ # end
13
+ #
14
+ # # response with content generated based on request
15
+ # stub.get '/showget' do |env|
16
+ # [200, {'Content-Type' => 'text/plain'}, env[:method].to_s]
17
+ # end
18
+ #
19
+ # # A regular expression can be used as matching filter
20
+ # stub.get /\A\/items\/(\d+)\z/ do |env, meta|
21
+ # # in case regular expression is used, an instance of MatchData
22
+ # # can be received
23
+ # [200,
24
+ # {'Content-Type' => 'text/plain'},
25
+ # "showing item: #{meta[:match_data][1]}"
26
+ # ]
27
+ # end
28
+ #
29
+ # # Test the request body is the same as the stubbed body
30
+ # stub.post('/bar', 'name=YK&word=call') { [200, {}, ''] }
31
+ #
32
+ # # You can pass a proc as a stubbed body and check the request body in your way.
33
+ # # In this case, the proc should return true or false.
34
+ # stub.post('/foo', ->(request_body) do
35
+ # JSON.parse(request_body).slice('name') == { 'name' => 'YK' } }) { [200, {}, '']
36
+ # end
37
+ #
38
+ # # You can set strict_mode to exactly match the stubbed requests.
39
+ # stub.strict_mode = true
7
40
  # end
8
41
  # end
9
- # end
10
42
  #
11
- # resp = test.get '/nigiri/sake.json'
12
- # resp.body # => 'hi world'
43
+ # resp = test.get '/resource.json'
44
+ # resp.body # => 'hi world'
13
45
  #
46
+ # resp = test.get '/showget'
47
+ # resp.body # => 'get'
48
+ #
49
+ # resp = test.get '/items/1'
50
+ # resp.body # => 'showing item: 1'
51
+ #
52
+ # resp = test.get '/items/2'
53
+ # resp.body # => 'showing item: 2'
54
+ #
55
+ # resp = test.post '/bar', 'name=YK&word=call'
56
+ # resp.status # => 200
57
+ #
58
+ # resp = test.post '/foo', JSON.dump(name: 'YK', created_at: Time.now)
59
+ # resp.status # => 200
14
60
  class Test < Faraday::Adapter
15
61
  attr_accessor :stubs
16
62
 
63
+ # A stack of Stubs
17
64
  class Stubs
18
65
  class NotFound < StandardError
19
66
  end
20
67
 
21
- def initialize
22
- # {:get => [Stub, Stub]}
23
- @stack, @consumed = {}, {}
68
+ def initialize(strict_mode: false)
69
+ # { get: [Stub, Stub] }
70
+ @stack = {}
71
+ @consumed = {}
72
+ @strict_mode = strict_mode
73
+ @stubs_mutex = Monitor.new
24
74
  yield(self) if block_given?
25
75
  end
26
76
 
@@ -28,17 +78,23 @@ module Faraday
28
78
  @stack.empty?
29
79
  end
30
80
 
31
- def match(request_method, path, headers, body)
32
- return false if !@stack.key?(request_method)
81
+ # @param env [Faraday::Env]
82
+ def match(env)
83
+ request_method = env[:method]
84
+ return false unless @stack.key?(request_method)
85
+
33
86
  stack = @stack[request_method]
34
87
  consumed = (@consumed[request_method] ||= [])
35
88
 
36
- if stub = matches?(stack, path, headers, body)
37
- consumed << stack.delete(stub)
38
- stub
39
- else
40
- matches?(consumed, path, headers, body)
89
+ @stubs_mutex.synchronize do
90
+ stub, meta = matches?(stack, env)
91
+ if stub
92
+ removed = stack.delete(stub)
93
+ consumed << removed unless removed.nil?
94
+ return stub, meta
95
+ end
41
96
  end
97
+ matches?(consumed, env)
42
98
  end
43
99
 
44
100
  def get(path, headers = {}, &block)
@@ -49,15 +105,15 @@ module Faraday
49
105
  new_stub(:head, path, headers, &block)
50
106
  end
51
107
 
52
- def post(path, body=nil, headers = {}, &block)
108
+ def post(path, body = nil, headers = {}, &block)
53
109
  new_stub(:post, path, headers, body, &block)
54
110
  end
55
111
 
56
- def put(path, body=nil, headers = {}, &block)
112
+ def put(path, body = nil, headers = {}, &block)
57
113
  new_stub(:put, path, headers, body, &block)
58
114
  end
59
115
 
60
- def patch(path, body=nil, headers = {}, &block)
116
+ def patch(path, body = nil, headers = {}, &block)
61
117
  new_stub(:patch, path, headers, body, &block)
62
118
  end
63
119
 
@@ -73,65 +129,131 @@ module Faraday
73
129
  def verify_stubbed_calls
74
130
  failed_stubs = []
75
131
  @stack.each do |method, stubs|
76
- unless stubs.size == 0
77
- failed_stubs.concat(stubs.map {|stub|
132
+ next if stubs.empty?
133
+
134
+ failed_stubs.concat(
135
+ stubs.map do |stub|
78
136
  "Expected #{method} #{stub}."
79
- })
137
+ end
138
+ )
139
+ end
140
+ raise failed_stubs.join(' ') unless failed_stubs.empty?
141
+ end
142
+
143
+ # Set strict_mode. If the value is true, this adapter tries to find matched requests strictly,
144
+ # which means that all of a path, parameters, and headers must be the same as an actual request.
145
+ def strict_mode=(value)
146
+ @strict_mode = value
147
+ @stack.each do |_method, stubs|
148
+ stubs.each do |stub|
149
+ stub.strict_mode = value
80
150
  end
81
151
  end
82
- raise failed_stubs.join(" ") unless failed_stubs.size == 0
83
152
  end
84
153
 
85
154
  protected
86
155
 
87
- def new_stub(request_method, path, headers = {}, body=nil, &block)
88
- normalized_path = Faraday::Utils.normalize_path(path)
89
- (@stack[request_method] ||= []) << Stub.new(normalized_path, headers, body, block)
156
+ def new_stub(request_method, path, headers = {}, body = nil, &block)
157
+ normalized_path, host =
158
+ if path.is_a?(Regexp)
159
+ path
160
+ else
161
+ [
162
+ Faraday::Utils.normalize_path(path),
163
+ Faraday::Utils.URI(path).host
164
+ ]
165
+ end
166
+ path, query = normalized_path.respond_to?(:split) ? normalized_path.split('?') : normalized_path
167
+ headers = Utils::Headers.new(headers)
168
+
169
+ stub = Stub.new(host, path, query, headers, body, @strict_mode, block)
170
+ (@stack[request_method] ||= []) << stub
90
171
  end
91
172
 
92
- def matches?(stack, path, headers, body)
93
- stack.detect { |stub| stub.matches?(path, headers, body) }
173
+ # @param stack [Hash]
174
+ # @param env [Faraday::Env]
175
+ def matches?(stack, env)
176
+ stack.each do |stub|
177
+ match_result, meta = stub.matches?(env)
178
+ return stub, meta if match_result
179
+ end
180
+ nil
94
181
  end
95
182
  end
96
183
 
97
- class Stub < Struct.new(:path, :params, :headers, :body, :block)
98
- def initialize(full, headers, body, block)
99
- path, query = full.split('?')
100
- params = query ?
101
- Faraday::Utils.parse_nested_query(query) :
102
- {}
103
- super(path, params, headers, body, block)
184
+ # Stub request
185
+ class Stub < Struct.new(:host, :path, :query, :headers, :body, :strict_mode, :block) # rubocop:disable Style/StructInheritance
186
+ # @param env [Faraday::Env]
187
+ def matches?(env)
188
+ request_host = env[:url].host
189
+ request_path = Faraday::Utils.normalize_path(env[:url].path)
190
+ request_headers = env.request_headers
191
+ request_body = env[:body]
192
+
193
+ # meta is a hash used as carrier
194
+ # that will be yielded to consumer block
195
+ meta = {}
196
+ [(host.nil? || host == request_host) &&
197
+ path_match?(request_path, meta) &&
198
+ params_match?(env) &&
199
+ body_match?(request_body) &&
200
+ headers_match?(request_headers), meta]
104
201
  end
105
202
 
106
- def matches?(request_uri, request_headers, request_body)
107
- request_path, request_query = request_uri.split('?')
108
- request_params = request_query ?
109
- Faraday::Utils.parse_nested_query(request_query) :
110
- {}
111
- request_path == path &&
112
- params_match?(request_params) &&
113
- (body.to_s.size.zero? || request_body == body) &&
114
- headers_match?(request_headers)
203
+ def path_match?(request_path, meta)
204
+ if path.is_a?(Regexp)
205
+ !!(meta[:match_data] = path.match(request_path))
206
+ else
207
+ path == request_path
208
+ end
115
209
  end
116
210
 
117
- def params_match?(request_params)
211
+ # @param env [Faraday::Env]
212
+ def params_match?(env)
213
+ request_params = env[:params]
214
+ params = env.params_encoder.decode(query) || {}
215
+
216
+ if strict_mode
217
+ return Set.new(params) == Set.new(request_params)
218
+ end
219
+
118
220
  params.keys.all? do |key|
119
221
  request_params[key] == params[key]
120
222
  end
121
223
  end
122
224
 
123
225
  def headers_match?(request_headers)
226
+ if strict_mode
227
+ headers_with_user_agent = headers.dup.tap do |hs|
228
+ # NOTE: Set User-Agent in case it's not set when creating Stubs.
229
+ # Users would not want to set Faraday's User-Agent explicitly.
230
+ hs[:user_agent] ||= Connection::USER_AGENT
231
+ end
232
+ return Set.new(headers_with_user_agent) == Set.new(request_headers)
233
+ end
234
+
124
235
  headers.keys.all? do |key|
125
236
  request_headers[key] == headers[key]
126
237
  end
127
238
  end
128
239
 
240
+ def body_match?(request_body)
241
+ return true if body.to_s.size.zero?
242
+
243
+ case body
244
+ when Proc
245
+ body.call(request_body)
246
+ else
247
+ request_body == body
248
+ end
249
+ end
250
+
129
251
  def to_s
130
252
  "#{path} #{body}"
131
253
  end
132
254
  end
133
255
 
134
- def initialize(app, stubs=nil, &block)
256
+ def initialize(app, stubs = nil, &block)
135
257
  super(app)
136
258
  @stubs = stubs || Stubs.new
137
259
  configure(&block) if block
@@ -141,22 +263,36 @@ module Faraday
141
263
  yield(stubs)
142
264
  end
143
265
 
266
+ # @param env [Faraday::Env]
144
267
  def call(env)
145
268
  super
146
- normalized_path = Faraday::Utils.normalize_path(env[:url])
147
- params_encoder = env.request.params_encoder || Faraday::Utils.default_params_encoder
148
-
149
- if stub = stubs.match(env[:method], normalized_path, env.request_headers, env[:body])
150
- env[:params] = (query = env[:url].query) ?
151
- params_encoder.decode(query) :
152
- {}
153
- status, headers, body = stub.block.call(env)
154
- save_response(env, status, body, headers)
155
- else
156
- raise Stubs::NotFound, "no stubbed request for #{env[:method]} #{normalized_path} #{env[:body]}"
269
+
270
+ env.request.params_encoder ||= Faraday::Utils.default_params_encoder
271
+ env[:params] = env.params_encoder.decode(env[:url].query) || {}
272
+ stub, meta = stubs.match(env)
273
+
274
+ unless stub
275
+ raise Stubs::NotFound, "no stubbed request for #{env[:method]} " \
276
+ "#{env[:url]} #{env[:body]}"
157
277
  end
278
+
279
+ block_arity = stub.block.arity
280
+ status, headers, body =
281
+ if block_arity >= 0
282
+ stub.block.call(*[env, meta].take(block_arity))
283
+ else
284
+ stub.block.call(env, meta)
285
+ end
286
+
287
+ # We need to explicitly pass `reason_phrase = nil` here to avoid keyword args conflicts.
288
+ # See https://github.com/lostisland/faraday/issues/1444
289
+ # TODO: remove `nil` explicit reason_phrase once Ruby 3.0 becomes minimum req. version
290
+ save_response(env, status, body, headers, nil)
291
+
158
292
  @app.call(env)
159
293
  end
160
294
  end
161
295
  end
162
296
  end
297
+
298
+ Faraday::Adapter.register_middleware(test: Faraday::Adapter::Test)
@@ -1,46 +1,102 @@
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
 
28
+ def initialize(_app = nil, opts = {}, &block)
29
+ @app = ->(env) { env.response }
30
+ @connection_options = opts
31
+ @config_block = block
32
+ end
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
+
33
55
  def call(env)
34
56
  env.clear_body if env.needs_body?
57
+ env.response = Response.new
35
58
  end
36
59
 
37
- def save_response(env, status, body, headers = nil)
60
+ private
61
+
62
+ def save_response(env, status, body, headers = nil, reason_phrase = nil, finished: true)
38
63
  env.status = status
39
64
  env.body = body
65
+ env.reason_phrase = reason_phrase&.to_s&.strip
40
66
  env.response_headers = Utils::Headers.new.tap do |response_headers|
41
67
  response_headers.update headers unless headers.nil?
42
68
  yield(response_headers) if block_given?
43
69
  end
70
+
71
+ env.response.finish(env) unless env.parallel? || !finished
72
+ env.response
44
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, :open_timeout, or
82
+ # :timeout
83
+ #
84
+ # @return [Integer, nil] Timeout duration in seconds, or nil if no timeout
85
+ # has been set.
86
+ def request_timeout(type, options)
87
+ key = TIMEOUT_KEYS.fetch(type) do
88
+ msg = "Expected :read, :write, :open. Got #{type.inspect} :("
89
+ raise ArgumentError, msg
90
+ end
91
+ options[key] || options[:timeout]
92
+ end
93
+
94
+ TIMEOUT_KEYS = {
95
+ read: :read_timeout,
96
+ open: :open_timeout,
97
+ write: :write_timeout
98
+ }.freeze
45
99
  end
46
100
  end
101
+
102
+ 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