faraday 0.11.0 → 1.4.3

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 (104) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +380 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +25 -229
  5. data/Rakefile +7 -0
  6. data/examples/client_spec.rb +65 -0
  7. data/examples/client_test.rb +79 -0
  8. data/lib/faraday/adapter/httpclient.rb +83 -59
  9. data/lib/faraday/adapter/patron.rb +92 -36
  10. data/lib/faraday/adapter/rack.rb +30 -13
  11. data/lib/faraday/adapter/test.rb +103 -62
  12. data/lib/faraday/adapter/typhoeus.rb +7 -115
  13. data/lib/faraday/adapter.rb +77 -22
  14. data/lib/faraday/adapter_registry.rb +30 -0
  15. data/lib/faraday/autoload.rb +42 -36
  16. data/lib/faraday/connection.rb +351 -167
  17. data/lib/faraday/dependency_loader.rb +37 -0
  18. data/lib/faraday/encoders/flat_params_encoder.rb +105 -0
  19. data/lib/faraday/encoders/nested_params_encoder.rb +176 -0
  20. data/lib/faraday/error.rb +127 -38
  21. data/lib/faraday/file_part.rb +128 -0
  22. data/lib/faraday/logging/formatter.rb +105 -0
  23. data/lib/faraday/methods.rb +6 -0
  24. data/lib/faraday/middleware.rb +19 -25
  25. data/lib/faraday/middleware_registry.rb +129 -0
  26. data/lib/faraday/options/connection_options.rb +22 -0
  27. data/lib/faraday/options/env.rb +181 -0
  28. data/lib/faraday/options/proxy_options.rb +32 -0
  29. data/lib/faraday/options/request_options.rb +22 -0
  30. data/lib/faraday/options/ssl_options.rb +59 -0
  31. data/lib/faraday/options.rb +58 -207
  32. data/lib/faraday/param_part.rb +53 -0
  33. data/lib/faraday/parameters.rb +4 -196
  34. data/lib/faraday/rack_builder.rb +84 -48
  35. data/lib/faraday/request/authorization.rb +44 -30
  36. data/lib/faraday/request/basic_authentication.rb +14 -7
  37. data/lib/faraday/request/instrumentation.rb +45 -27
  38. data/lib/faraday/request/multipart.rb +88 -45
  39. data/lib/faraday/request/retry.rb +211 -126
  40. data/lib/faraday/request/token_authentication.rb +15 -10
  41. data/lib/faraday/request/url_encoded.rb +43 -23
  42. data/lib/faraday/request.rb +94 -32
  43. data/lib/faraday/response/logger.rb +22 -69
  44. data/lib/faraday/response/raise_error.rb +49 -14
  45. data/lib/faraday/response.rb +27 -23
  46. data/lib/faraday/utils/headers.rb +139 -0
  47. data/lib/faraday/utils/params_hash.rb +61 -0
  48. data/lib/faraday/utils.rb +38 -238
  49. data/lib/faraday/version.rb +5 -0
  50. data/lib/faraday.rb +124 -187
  51. data/spec/external_adapters/faraday_specs_setup.rb +14 -0
  52. data/spec/faraday/adapter/em_http_spec.rb +47 -0
  53. data/spec/faraday/adapter/em_synchrony_spec.rb +16 -0
  54. data/spec/faraday/adapter/excon_spec.rb +49 -0
  55. data/spec/faraday/adapter/httpclient_spec.rb +73 -0
  56. data/spec/faraday/adapter/net_http_spec.rb +64 -0
  57. data/spec/faraday/adapter/patron_spec.rb +18 -0
  58. data/spec/faraday/adapter/rack_spec.rb +8 -0
  59. data/spec/faraday/adapter/test_spec.rb +260 -0
  60. data/spec/faraday/adapter/typhoeus_spec.rb +7 -0
  61. data/spec/faraday/adapter_registry_spec.rb +28 -0
  62. data/spec/faraday/adapter_spec.rb +55 -0
  63. data/spec/faraday/composite_read_io_spec.rb +80 -0
  64. data/spec/faraday/connection_spec.rb +736 -0
  65. data/spec/faraday/error_spec.rb +60 -0
  66. data/spec/faraday/middleware_spec.rb +52 -0
  67. data/spec/faraday/options/env_spec.rb +70 -0
  68. data/spec/faraday/options/options_spec.rb +297 -0
  69. data/spec/faraday/options/proxy_options_spec.rb +44 -0
  70. data/spec/faraday/options/request_options_spec.rb +19 -0
  71. data/spec/faraday/params_encoders/flat_spec.rb +42 -0
  72. data/spec/faraday/params_encoders/nested_spec.rb +142 -0
  73. data/spec/faraday/rack_builder_spec.rb +345 -0
  74. data/spec/faraday/request/authorization_spec.rb +88 -0
  75. data/spec/faraday/request/instrumentation_spec.rb +76 -0
  76. data/spec/faraday/request/multipart_spec.rb +302 -0
  77. data/spec/faraday/request/retry_spec.rb +242 -0
  78. data/spec/faraday/request/url_encoded_spec.rb +83 -0
  79. data/spec/faraday/request_spec.rb +120 -0
  80. data/spec/faraday/response/logger_spec.rb +220 -0
  81. data/spec/faraday/response/middleware_spec.rb +68 -0
  82. data/spec/faraday/response/raise_error_spec.rb +169 -0
  83. data/spec/faraday/response_spec.rb +75 -0
  84. data/spec/faraday/utils/headers_spec.rb +82 -0
  85. data/spec/faraday/utils_spec.rb +56 -0
  86. data/spec/faraday_spec.rb +37 -0
  87. data/spec/spec_helper.rb +132 -0
  88. data/spec/support/disabling_stub.rb +14 -0
  89. data/spec/support/fake_safe_buffer.rb +15 -0
  90. data/spec/support/helper_methods.rb +133 -0
  91. data/spec/support/shared_examples/adapter.rb +105 -0
  92. data/spec/support/shared_examples/params_encoder.rb +18 -0
  93. data/spec/support/shared_examples/request_method.rb +262 -0
  94. data/spec/support/streaming_response_checker.rb +35 -0
  95. data/spec/support/webmock_rack_app.rb +68 -0
  96. metadata +164 -16
  97. data/lib/faraday/adapter/em_http.rb +0 -243
  98. data/lib/faraday/adapter/em_http_ssl_patch.rb +0 -56
  99. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +0 -66
  100. data/lib/faraday/adapter/em_synchrony.rb +0 -106
  101. data/lib/faraday/adapter/excon.rb +0 -80
  102. data/lib/faraday/adapter/net_http.rb +0 -135
  103. data/lib/faraday/adapter/net_http_persistent.rb +0 -50
  104. data/lib/faraday/upload_io.rb +0 -67
@@ -1,51 +1,56 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Faraday
2
4
  class Adapter
3
- # Examples
4
- #
5
+ # @example
5
6
  # test = Faraday::Connection.new do
6
7
  # use Faraday::Adapter::Test do |stub|
7
- # # simply define matcher to match the request
8
+ # # Define matcher to match the request
8
9
  # stub.get '/resource.json' do
9
10
  # # return static content
10
11
  # [200, {'Content-Type' => 'application/json'}, 'hi world']
11
12
  # end
12
- #
13
+ #
13
14
  # # response with content generated based on request
14
15
  # stub.get '/showget' do |env|
15
16
  # [200, {'Content-Type' => 'text/plain'}, env[:method].to_s]
16
17
  # end
17
- #
18
- # # regular expression can be used as matching filter
18
+ #
19
+ # # A regular expression can be used as matching filter
19
20
  # 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]}"]
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
+ # ]
22
27
  # end
23
28
  # end
24
29
  # end
25
- #
30
+ #
26
31
  # resp = test.get '/resource.json'
27
32
  # resp.body # => 'hi world'
28
- #
33
+ #
29
34
  # resp = test.get '/showget'
30
35
  # resp.body # => 'get'
31
- #
36
+ #
32
37
  # resp = test.get '/items/1'
33
38
  # resp.body # => 'showing item: 1'
34
- #
39
+ #
35
40
  # resp = test.get '/items/2'
36
41
  # resp.body # => 'showing item: 2'
37
- #
38
-
39
42
  class Test < Faraday::Adapter
40
43
  attr_accessor :stubs
41
44
 
45
+ # A stack of Stubs
42
46
  class Stubs
43
47
  class NotFound < StandardError
44
48
  end
45
49
 
46
50
  def initialize
47
- # {:get => [Stub, Stub]}
48
- @stack, @consumed = {}, {}
51
+ # { get: [Stub, Stub] }
52
+ @stack = {}
53
+ @consumed = {}
49
54
  yield(self) if block_given?
50
55
  end
51
56
 
@@ -53,17 +58,18 @@ module Faraday
53
58
  @stack.empty?
54
59
  end
55
60
 
56
- def match(request_method, path, headers, body)
57
- return false if !@stack.key?(request_method)
61
+ def match(request_method, host, path, headers, body)
62
+ return false unless @stack.key?(request_method)
63
+
58
64
  stack = @stack[request_method]
59
65
  consumed = (@consumed[request_method] ||= [])
60
66
 
61
- stub, meta = matches?(stack, path, headers, body)
67
+ stub, meta = matches?(stack, host, path, headers, body)
62
68
  if stub
63
69
  consumed << stack.delete(stub)
64
70
  return stub, meta
65
71
  end
66
- matches?(consumed, path, headers, body)
72
+ matches?(consumed, host, path, headers, body)
67
73
  end
68
74
 
69
75
  def get(path, headers = {}, &block)
@@ -74,15 +80,15 @@ module Faraday
74
80
  new_stub(:head, path, headers, &block)
75
81
  end
76
82
 
77
- def post(path, body=nil, headers = {}, &block)
83
+ def post(path, body = nil, headers = {}, &block)
78
84
  new_stub(:post, path, headers, body, &block)
79
85
  end
80
86
 
81
- def put(path, body=nil, headers = {}, &block)
87
+ def put(path, body = nil, headers = {}, &block)
82
88
  new_stub(:put, path, headers, body, &block)
83
89
  end
84
90
 
85
- def patch(path, body=nil, headers = {}, &block)
91
+ def patch(path, body = nil, headers = {}, &block)
86
92
  new_stub(:patch, path, headers, body, &block)
87
93
  end
88
94
 
@@ -98,56 +104,79 @@ module Faraday
98
104
  def verify_stubbed_calls
99
105
  failed_stubs = []
100
106
  @stack.each do |method, stubs|
101
- unless stubs.size == 0
102
- failed_stubs.concat(stubs.map {|stub|
107
+ next if stubs.empty?
108
+
109
+ failed_stubs.concat(
110
+ stubs.map do |stub|
103
111
  "Expected #{method} #{stub}."
104
- })
105
- end
112
+ end
113
+ )
106
114
  end
107
- raise failed_stubs.join(" ") unless failed_stubs.size == 0
115
+ raise failed_stubs.join(' ') unless failed_stubs.empty?
108
116
  end
109
117
 
110
118
  protected
111
119
 
112
- def new_stub(request_method, path, headers = {}, body=nil, &block)
113
- normalized_path = path.is_a?(Regexp) ? path : Faraday::Utils.normalize_path(path)
114
- (@stack[request_method] ||= []) << Stub.new(normalized_path, headers, body, block)
120
+ def new_stub(request_method, path, headers = {}, body = nil, &block)
121
+ normalized_path, host =
122
+ if path.is_a?(Regexp)
123
+ path
124
+ else
125
+ [
126
+ Faraday::Utils.normalize_path(path),
127
+ Faraday::Utils.URI(path).host
128
+ ]
129
+ end
130
+
131
+ stub = Stub.new(host, normalized_path, headers, body, block)
132
+ (@stack[request_method] ||= []) << stub
115
133
  end
116
134
 
117
- def matches?(stack, path, headers, body)
135
+ def matches?(stack, host, path, headers, body)
118
136
  stack.each do |stub|
119
- match_result, meta = stub.matches?(path, headers, body)
137
+ match_result, meta = stub.matches?(host, path, headers, body)
120
138
  return stub, meta if match_result
121
139
  end
122
140
  nil
123
141
  end
124
142
  end
125
143
 
126
- class Stub < Struct.new(:path, :params, :headers, :body, :block)
127
- def initialize(full, headers, body, block)
128
- path, query = full.respond_to?(:split) ? full.split("?") : full
129
- params = query ?
130
- Faraday::Utils.parse_nested_query(query) :
131
- {}
132
- super(path, params, headers, body, block)
144
+ # Stub request
145
+ # rubocop:disable Style/StructInheritance
146
+ class Stub < Struct.new(:host, :path, :params, :headers, :body, :block)
147
+ # rubocop:enable Style/StructInheritance
148
+ def initialize(host, full, headers, body, block)
149
+ path, query = full.respond_to?(:split) ? full.split('?') : full
150
+ params =
151
+ if query
152
+ Faraday::Utils.parse_nested_query(query)
153
+ else
154
+ {}
155
+ end
156
+
157
+ super(host, path, params, headers, body, block)
133
158
  end
134
159
 
135
- def matches?(request_uri, request_headers, request_body)
160
+ def matches?(request_host, request_uri, request_headers, request_body)
136
161
  request_path, request_query = request_uri.split('?')
137
- request_params = request_query ?
138
- Faraday::Utils.parse_nested_query(request_query) :
139
- {}
140
- # meta is a hash use as carrier
162
+ request_params =
163
+ if request_query
164
+ Faraday::Utils.parse_nested_query(request_query)
165
+ else
166
+ {}
167
+ end
168
+ # meta is a hash used as carrier
141
169
  # that will be yielded to consumer block
142
170
  meta = {}
143
- return path_match?(request_path, meta) &&
171
+ [(host.nil? || host == request_host) &&
172
+ path_match?(request_path, meta) &&
144
173
  params_match?(request_params) &&
145
174
  (body.to_s.size.zero? || request_body == body) &&
146
- headers_match?(request_headers), meta
175
+ headers_match?(request_headers), meta]
147
176
  end
148
177
 
149
178
  def path_match?(request_path, meta)
150
- if path.is_a? Regexp
179
+ if path.is_a?(Regexp)
151
180
  !!(meta[:match_data] = path.match(request_path))
152
181
  else
153
182
  path == request_path
@@ -171,7 +200,7 @@ module Faraday
171
200
  end
172
201
  end
173
202
 
174
- def initialize(app, stubs=nil, &block)
203
+ def initialize(app, stubs = nil, &block)
175
204
  super(app)
176
205
  @stubs = stubs || Stubs.new
177
206
  configure(&block) if block
@@ -183,21 +212,33 @@ module Faraday
183
212
 
184
213
  def call(env)
185
214
  super
215
+ host = env[:url].host
186
216
  normalized_path = Faraday::Utils.normalize_path(env[:url])
187
- params_encoder = env.request.params_encoder || Faraday::Utils.default_params_encoder
188
-
189
- stub, meta = stubs.match(env[:method], normalized_path, env.request_headers, env[:body])
190
- if stub
191
- env[:params] = (query = env[:url].query) ?
192
- params_encoder.decode(query) : {}
193
- block_arity = stub.block.arity
194
- status, headers, body = (block_arity >= 0) ?
195
- stub.block.call(*[env, meta].take(block_arity)) :
217
+ params_encoder = env.request.params_encoder ||
218
+ Faraday::Utils.default_params_encoder
219
+
220
+ stub, meta = stubs.match(env[:method], host, normalized_path,
221
+ env.request_headers, env[:body])
222
+
223
+ unless stub
224
+ raise Stubs::NotFound, "no stubbed request for #{env[:method]} "\
225
+ "#{normalized_path} #{env[:body]}"
226
+ end
227
+
228
+ env[:params] = if (query = env[:url].query)
229
+ params_encoder.decode(query)
230
+ else
231
+ {}
232
+ end
233
+ block_arity = stub.block.arity
234
+ status, headers, body =
235
+ if block_arity >= 0
236
+ stub.block.call(*[env, meta].take(block_arity))
237
+ else
196
238
  stub.block.call(env, meta)
197
- save_response(env, status, body, headers)
198
- else
199
- raise Stubs::NotFound, "no stubbed request for #{env[:method]} #{normalized_path} #{env[:body]}"
200
- end
239
+ end
240
+ save_response(env, status, body, headers)
241
+
201
242
  @app.call(env)
202
243
  end
203
244
  end
@@ -1,123 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Faraday
2
4
  class Adapter
5
+ # Typhoeus adapter. This class is just a stub, the real adapter is in
6
+ # https://github.com/typhoeus/typhoeus/blob/master/lib/typhoeus/adapters/faraday.rb
3
7
  class Typhoeus < Faraday::Adapter
4
- self.supports_parallel = true
5
-
6
- def self.setup_parallel_manager(options = {})
7
- options.empty? ? ::Typhoeus::Hydra.hydra : ::Typhoeus::Hydra.new(options)
8
- end
8
+ # Needs to define this method in order to support Typhoeus <= 1.3.0
9
+ def call; end
9
10
 
10
11
  dependency 'typhoeus'
11
-
12
- def call(env)
13
- super
14
- perform_request env
15
- @app.call env
16
- end
17
-
18
- def perform_request(env)
19
- read_body env
20
-
21
- hydra = env[:parallel_manager] || self.class.setup_parallel_manager
22
- hydra.queue request(env)
23
- hydra.run unless parallel?(env)
24
- rescue Errno::ECONNREFUSED
25
- raise Error::ConnectionFailed, $!
26
- end
27
-
28
- # TODO: support streaming requests
29
- def read_body(env)
30
- env[:body] = env[:body].read if env[:body].respond_to? :read
31
- end
32
-
33
- def request(env)
34
- method = env[:method]
35
- # For some reason, prevents Typhoeus from using "100-continue".
36
- # We want this because Webrick 1.3.1 can't seem to handle it w/ PUT.
37
- method = method.to_s.upcase if method == :put
38
-
39
- req = ::Typhoeus::Request.new env[:url].to_s,
40
- :method => method,
41
- :body => env[:body],
42
- :headers => env[:request_headers],
43
- :disable_ssl_peer_verification => (env[:ssl] && env[:ssl].disable?)
44
-
45
- configure_ssl req, env
46
- configure_proxy req, env
47
- configure_timeout req, env
48
- configure_socket req, env
49
-
50
- req.on_complete do |resp|
51
- if resp.timed_out?
52
- if parallel?(env)
53
- # TODO: error callback in async mode
54
- else
55
- raise Faraday::Error::TimeoutError, "request timed out"
56
- end
57
- end
58
-
59
- case resp.curl_return_code
60
- when 0
61
- # everything OK
62
- when 7
63
- raise Error::ConnectionFailed, resp.curl_error_message
64
- when 60
65
- raise Faraday::SSLError, resp.curl_error_message
66
- else
67
- raise Error::ClientError, resp.curl_error_message
68
- end
69
-
70
- save_response(env, resp.code, resp.body) do |response_headers|
71
- response_headers.parse resp.headers
72
- end
73
- # in async mode, :response is initialized at this point
74
- env[:response].finish(env) if parallel?(env)
75
- end
76
-
77
- req
78
- end
79
-
80
- def configure_ssl(req, env)
81
- ssl = env[:ssl]
82
-
83
- req.ssl_version = ssl[:version] if ssl[:version]
84
- req.ssl_cert = ssl[:client_cert] if ssl[:client_cert]
85
- req.ssl_key = ssl[:client_key] if ssl[:client_key]
86
- req.ssl_cacert = ssl[:ca_file] if ssl[:ca_file]
87
- req.ssl_capath = ssl[:ca_path] if ssl[:ca_path]
88
- end
89
-
90
- def configure_proxy(req, env)
91
- proxy = request_options(env)[:proxy]
92
- return unless proxy
93
-
94
- req.proxy = "#{proxy[:uri].host}:#{proxy[:uri].port}"
95
-
96
- if proxy[:user] && proxy[:password]
97
- req.proxy_username = proxy[:user]
98
- req.proxy_password = proxy[:password]
99
- end
100
- end
101
-
102
- def configure_timeout(req, env)
103
- env_req = request_options(env)
104
- req.timeout = req.connect_timeout = (env_req[:timeout] * 1000) if env_req[:timeout]
105
- req.connect_timeout = (env_req[:open_timeout] * 1000) if env_req[:open_timeout]
106
- end
107
-
108
- def configure_socket(req, env)
109
- if bind = request_options(env)[:bind]
110
- req.interface = bind[:host]
111
- end
112
- end
113
-
114
- def request_options(env)
115
- env[:request]
116
- end
117
-
118
- def parallel?(env)
119
- !!env[:parallel_manager]
120
- end
12
+ dependency 'typhoeus/adapters/faraday'
121
13
  end
122
14
  end
123
15
  end
@@ -1,53 +1,108 @@
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
+ extend DependencyLoader
9
+
10
+ CONTENT_LENGTH = 'Content-Length'
11
+
12
+ register_middleware File.expand_path('adapter', __dir__),
13
+ test: [:Test, 'test'],
14
+ typhoeus: [:Typhoeus, 'typhoeus'],
15
+ patron: [:Patron, 'patron'],
16
+ rack: [:Rack, 'rack'],
17
+ httpclient: [:HTTPClient, 'httpclient']
18
+
19
+ # This module marks an Adapter as supporting parallel requests.
20
20
  module Parallelism
21
21
  attr_writer :supports_parallel
22
- def supports_parallel?() @supports_parallel end
22
+
23
+ def supports_parallel?
24
+ @supports_parallel
25
+ end
23
26
 
24
27
  def inherited(subclass)
25
28
  super
26
- subclass.supports_parallel = self.supports_parallel?
29
+ subclass.supports_parallel = supports_parallel?
27
30
  end
28
31
  end
29
32
 
30
33
  extend Parallelism
31
34
  self.supports_parallel = false
32
35
 
33
- def initialize(app = nil, opts = {}, &block)
34
- super(app)
36
+ def initialize(_app = nil, opts = {}, &block)
37
+ @app = ->(env) { env.response }
35
38
  @connection_options = opts
36
39
  @config_block = block
37
40
  end
38
41
 
42
+ # Yields or returns an adapter's configured connection. Depends on
43
+ # #build_connection being defined on this adapter.
44
+ #
45
+ # @param env [Faraday::Env, Hash] The env object for a faraday request.
46
+ #
47
+ # @return The return value of the given block, or the HTTP connection object
48
+ # if no block is given.
49
+ def connection(env)
50
+ conn = build_connection(env)
51
+ return conn unless block_given?
52
+
53
+ yield conn
54
+ end
55
+
56
+ # Close any persistent connections. The adapter should still be usable
57
+ # after calling close.
58
+ def close
59
+ # Possible implementation:
60
+ # @app.close if @app.respond_to?(:close)
61
+ end
62
+
39
63
  def call(env)
40
64
  env.clear_body if env.needs_body?
65
+ env.response = Response.new
41
66
  end
42
67
 
68
+ private
69
+
43
70
  def save_response(env, status, body, headers = nil, reason_phrase = nil)
44
71
  env.status = status
45
72
  env.body = body
46
- env.reason_phrase = reason_phrase && reason_phrase.to_s.strip
73
+ env.reason_phrase = reason_phrase&.to_s&.strip
47
74
  env.response_headers = Utils::Headers.new.tap do |response_headers|
48
75
  response_headers.update headers unless headers.nil?
49
76
  yield(response_headers) if block_given?
50
77
  end
78
+
79
+ env.response.finish(env) unless env.parallel?
80
+ env.response
81
+ end
82
+
83
+ # Fetches either a read, write, or open timeout setting. Defaults to the
84
+ # :timeout value if a more specific one is not given.
85
+ #
86
+ # @param type [Symbol] Describes which timeout setting to get: :read,
87
+ # :write, or :open.
88
+ # @param options [Hash] Hash containing Symbol keys like :timeout,
89
+ # :read_timeout, :write_timeout, :open_timeout, or
90
+ # :timeout
91
+ #
92
+ # @return [Integer, nil] Timeout duration in seconds, or nil if no timeout
93
+ # has been set.
94
+ def request_timeout(type, options)
95
+ key = TIMEOUT_KEYS.fetch(type) do
96
+ msg = "Expected :read, :write, :open. Got #{type.inspect} :("
97
+ raise ArgumentError, msg
98
+ end
99
+ options[key] || options[:timeout]
51
100
  end
101
+
102
+ TIMEOUT_KEYS = {
103
+ read: :read_timeout,
104
+ open: :open_timeout,
105
+ write: :write_timeout
106
+ }.freeze
52
107
  end
53
108
  end
@@ -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