faraday 0.9.2 → 1.0.0

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 (103) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +276 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +27 -217
  5. data/Rakefile +7 -0
  6. data/UPGRADING.md +55 -0
  7. data/examples/client_spec.rb +65 -0
  8. data/examples/client_test.rb +79 -0
  9. data/lib/faraday/adapter/em_http.rb +149 -101
  10. data/lib/faraday/adapter/em_http_ssl_patch.rb +25 -19
  11. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +18 -15
  12. data/lib/faraday/adapter/em_synchrony.rb +106 -56
  13. data/lib/faraday/adapter/excon.rb +98 -55
  14. data/lib/faraday/adapter/httpclient.rb +89 -55
  15. data/lib/faraday/adapter/net_http.rb +132 -53
  16. data/lib/faraday/adapter/net_http_persistent.rb +70 -28
  17. data/lib/faraday/adapter/patron.rb +92 -38
  18. data/lib/faraday/adapter/rack.rb +30 -13
  19. data/lib/faraday/adapter/test.rb +136 -52
  20. data/lib/faraday/adapter/typhoeus.rb +7 -115
  21. data/lib/faraday/adapter.rb +89 -20
  22. data/lib/faraday/adapter_registry.rb +28 -0
  23. data/lib/faraday/autoload.rb +47 -36
  24. data/lib/faraday/connection.rb +345 -168
  25. data/lib/faraday/dependency_loader.rb +37 -0
  26. data/lib/faraday/encoders/flat_params_encoder.rb +98 -0
  27. data/lib/faraday/encoders/nested_params_encoder.rb +171 -0
  28. data/lib/faraday/error.rb +108 -29
  29. data/lib/faraday/file_part.rb +128 -0
  30. data/lib/faraday/logging/formatter.rb +105 -0
  31. data/lib/faraday/middleware.rb +12 -28
  32. data/lib/faraday/middleware_registry.rb +129 -0
  33. data/lib/faraday/options/connection_options.rb +22 -0
  34. data/lib/faraday/options/env.rb +181 -0
  35. data/lib/faraday/options/proxy_options.rb +28 -0
  36. data/lib/faraday/options/request_options.rb +22 -0
  37. data/lib/faraday/options/ssl_options.rb +59 -0
  38. data/lib/faraday/options.rb +57 -194
  39. data/lib/faraday/param_part.rb +53 -0
  40. data/lib/faraday/parameters.rb +4 -196
  41. data/lib/faraday/rack_builder.rb +74 -39
  42. data/lib/faraday/request/authorization.rb +42 -31
  43. data/lib/faraday/request/basic_authentication.rb +14 -7
  44. data/lib/faraday/request/instrumentation.rb +45 -27
  45. data/lib/faraday/request/multipart.rb +81 -45
  46. data/lib/faraday/request/retry.rb +211 -126
  47. data/lib/faraday/request/token_authentication.rb +15 -10
  48. data/lib/faraday/request/url_encoded.rb +41 -23
  49. data/lib/faraday/request.rb +84 -30
  50. data/lib/faraday/response/logger.rb +22 -48
  51. data/lib/faraday/response/raise_error.rb +38 -14
  52. data/lib/faraday/response.rb +27 -16
  53. data/lib/faraday/utils/headers.rb +139 -0
  54. data/lib/faraday/utils/params_hash.rb +61 -0
  55. data/lib/faraday/utils.rb +28 -228
  56. data/lib/faraday.rb +102 -204
  57. data/spec/external_adapters/faraday_specs_setup.rb +14 -0
  58. data/spec/faraday/adapter/em_http_spec.rb +47 -0
  59. data/spec/faraday/adapter/em_synchrony_spec.rb +16 -0
  60. data/spec/faraday/adapter/excon_spec.rb +49 -0
  61. data/spec/faraday/adapter/httpclient_spec.rb +73 -0
  62. data/spec/faraday/adapter/net_http_persistent_spec.rb +57 -0
  63. data/spec/faraday/adapter/net_http_spec.rb +64 -0
  64. data/spec/faraday/adapter/patron_spec.rb +18 -0
  65. data/spec/faraday/adapter/rack_spec.rb +8 -0
  66. data/spec/faraday/adapter/typhoeus_spec.rb +7 -0
  67. data/spec/faraday/adapter_registry_spec.rb +28 -0
  68. data/spec/faraday/adapter_spec.rb +55 -0
  69. data/spec/faraday/composite_read_io_spec.rb +80 -0
  70. data/spec/faraday/connection_spec.rb +691 -0
  71. data/spec/faraday/error_spec.rb +45 -0
  72. data/spec/faraday/middleware_spec.rb +26 -0
  73. data/spec/faraday/options/env_spec.rb +70 -0
  74. data/spec/faraday/options/options_spec.rb +297 -0
  75. data/spec/faraday/options/proxy_options_spec.rb +37 -0
  76. data/spec/faraday/options/request_options_spec.rb +19 -0
  77. data/spec/faraday/params_encoders/flat_spec.rb +34 -0
  78. data/spec/faraday/params_encoders/nested_spec.rb +134 -0
  79. data/spec/faraday/rack_builder_spec.rb +196 -0
  80. data/spec/faraday/request/authorization_spec.rb +88 -0
  81. data/spec/faraday/request/instrumentation_spec.rb +76 -0
  82. data/spec/faraday/request/multipart_spec.rb +274 -0
  83. data/spec/faraday/request/retry_spec.rb +242 -0
  84. data/spec/faraday/request/url_encoded_spec.rb +70 -0
  85. data/spec/faraday/request_spec.rb +109 -0
  86. data/spec/faraday/response/logger_spec.rb +220 -0
  87. data/spec/faraday/response/middleware_spec.rb +52 -0
  88. data/spec/faraday/response/raise_error_spec.rb +106 -0
  89. data/spec/faraday/response_spec.rb +75 -0
  90. data/spec/faraday/utils/headers_spec.rb +82 -0
  91. data/spec/faraday/utils_spec.rb +56 -0
  92. data/spec/faraday_spec.rb +37 -0
  93. data/spec/spec_helper.rb +132 -0
  94. data/spec/support/disabling_stub.rb +14 -0
  95. data/spec/support/fake_safe_buffer.rb +15 -0
  96. data/spec/support/helper_methods.rb +133 -0
  97. data/spec/support/shared_examples/adapter.rb +104 -0
  98. data/spec/support/shared_examples/params_encoder.rb +18 -0
  99. data/spec/support/shared_examples/request_method.rb +234 -0
  100. data/spec/support/streaming_response_checker.rb +35 -0
  101. data/spec/support/webmock_rack_app.rb +68 -0
  102. metadata +110 -64
  103. data/lib/faraday/upload_io.rb +0 -67
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Faraday
2
- # Public: Connection objects manage the default properties and the middleware
4
+ # Connection objects manage the default properties and the middleware
3
5
  # stack for fulfilling an HTTP request.
4
6
  #
5
- # Examples
7
+ # @example
6
8
  #
7
9
  # conn = Faraday::Connection.new 'http://sushi.com'
8
10
  #
@@ -12,54 +14,57 @@ module Faraday
12
14
  #
13
15
  class Connection
14
16
  # A Set of allowed HTTP verbs.
15
- METHODS = Set.new [:get, :post, :put, :delete, :head, :patch, :options]
17
+ METHODS = Set.new %i[get post put delete head patch options trace]
16
18
 
17
- # Public: Returns a Hash of URI query unencoded key/value pairs.
19
+ # @return [Hash] URI query unencoded key/value pairs.
18
20
  attr_reader :params
19
21
 
20
- # Public: Returns a Hash of unencoded HTTP header key/value pairs.
22
+ # @return [Hash] unencoded HTTP header key/value pairs.
21
23
  attr_reader :headers
22
24
 
23
- # Public: Returns a URI with the prefix used for all requests from this
24
- # Connection. This includes a default host name, scheme, port, and path.
25
+ # @return [String] a URI with the prefix used for all requests from this
26
+ # Connection. This includes a default host name, scheme, port, and path.
25
27
  attr_reader :url_prefix
26
28
 
27
- # Public: Returns the Faraday::Builder for this Connection.
29
+ # @return [Faraday::Builder] Builder for this Connection.
28
30
  attr_reader :builder
29
31
 
30
- # Public: Returns a Hash of the request options.
31
- attr_reader :options
32
-
33
- # Public: Returns a Hash of the SSL options.
32
+ # @return [Hash] SSL options.
34
33
  attr_reader :ssl
35
34
 
36
- # Public: Returns the parallel manager for this Connection.
35
+ # @return [Object] the parallel manager for this Connection.
37
36
  attr_reader :parallel_manager
38
37
 
39
- # Public: Sets the default parallel manager for this connection.
38
+ # Sets the default parallel manager for this connection.
40
39
  attr_writer :default_parallel_manager
41
40
 
42
- # Public: Initializes a new Faraday::Connection.
41
+ # @return [Hash] proxy options.
42
+ attr_reader :proxy
43
+
44
+ # Initializes a new Faraday::Connection.
43
45
  #
44
- # url - URI or String base URL to use as a prefix for all
46
+ # @param url [URI, String] URI or String base URL to use as a prefix for all
45
47
  # requests (optional).
46
- # options - Hash or Faraday::ConnectionOptions.
47
- # :url - URI or String base URL (default: "http:/").
48
- # :params - Hash of URI query unencoded key/value pairs.
49
- # :headers - Hash of unencoded HTTP header key/value pairs.
50
- # :request - Hash of request options.
51
- # :ssl - Hash of SSL options.
52
- # :proxy - URI, String or Hash of HTTP proxy options
53
- # (default: "http_proxy" environment variable).
54
- # :uri - URI or String
55
- # :user - String (optional)
56
- # :password - String (optional)
48
+ # @param options [Hash, Faraday::ConnectionOptions]
49
+ # @option options [URI, String] :url ('http:/') URI or String base URL
50
+ # @option options [Hash<String => String>] :params URI query unencoded
51
+ # key/value pairs.
52
+ # @option options [Hash<String => String>] :headers Hash of unencoded HTTP
53
+ # header key/value pairs.
54
+ # @option options [Hash] :request Hash of request options.
55
+ # @option options [Hash] :ssl Hash of SSL options.
56
+ # @option options [Hash, URI, String] :proxy proxy options, either as a URL
57
+ # or as a Hash
58
+ # @option options [URI, String] :proxy[:uri]
59
+ # @option options [String] :proxy[:user]
60
+ # @option options [String] :proxy[:password]
61
+ # @yield [self] after all setup has been done
57
62
  def initialize(url = nil, options = nil)
58
- if url.is_a?(Hash)
59
- options = ConnectionOptions.from(url)
63
+ options = ConnectionOptions.from(options)
64
+
65
+ if url.is_a?(Hash) || url.is_a?(ConnectionOptions)
66
+ options = options.merge(url)
60
67
  url = options.url
61
- else
62
- options = ConnectionOptions.from(options)
63
68
  end
64
69
 
65
70
  @parallel_manager = nil
@@ -71,7 +76,7 @@ module Faraday
71
76
 
72
77
  @builder = options.builder || begin
73
78
  # pass an empty block to Builder so it doesn't assume default middleware
74
- options.new_builder(block_given? ? Proc.new { |b| } : nil)
79
+ options.new_builder(block_given? ? proc { |b| } : nil)
75
80
  end
76
81
 
77
82
  self.url_prefix = url || 'http:/'
@@ -79,26 +84,31 @@ module Faraday
79
84
  @params.update(options.params) if options.params
80
85
  @headers.update(options.headers) if options.headers
81
86
 
82
- @proxy = nil
83
- proxy(options.fetch(:proxy) {
84
- uri = ENV['http_proxy']
85
- if uri && !uri.empty?
86
- uri = 'http://' + uri if uri !~ /^http/i
87
- uri
88
- end
89
- })
87
+ initialize_proxy(url, options)
90
88
 
91
89
  yield(self) if block_given?
92
90
 
93
91
  @headers[:user_agent] ||= "Faraday v#{VERSION}"
94
92
  end
95
93
 
96
- # Public: Sets the Hash of URI query unencoded key/value pairs.
94
+ def initialize_proxy(url, options)
95
+ @manual_proxy = !!options.proxy
96
+ @proxy =
97
+ if options.proxy
98
+ ProxyOptions.from(options.proxy)
99
+ else
100
+ proxy_from_env(url)
101
+ end
102
+ end
103
+
104
+ # Sets the Hash of URI query unencoded key/value pairs.
105
+ # @param hash [Hash]
97
106
  def params=(hash)
98
107
  @params.replace hash
99
108
  end
100
109
 
101
- # Public: Sets the Hash of unencoded HTTP header key/value pairs.
110
+ # Sets the Hash of unencoded HTTP header key/value pairs.
111
+ # @param hash [Hash]
102
112
  def headers=(hash)
103
113
  @headers.replace hash
104
114
  end
@@ -107,71 +117,163 @@ module Faraday
107
117
 
108
118
  def_delegators :builder, :build, :use, :request, :response, :adapter, :app
109
119
 
110
- # Public: Makes an HTTP request without a body.
120
+ # Closes the underlying resources and/or connections. In the case of
121
+ # persistent connections, this closes all currently open connections
122
+ # but does not prevent new connections from being made.
123
+ def close
124
+ app.close
125
+ end
126
+
127
+ # @!method get(url = nil, params = nil, headers = nil)
128
+ # Makes a GET HTTP request without a body.
129
+ # @!scope class
111
130
  #
112
- # url - The optional String base URL to use as a prefix for all
113
- # requests. Can also be the options Hash.
114
- # params - Hash of URI query unencoded key/value pairs.
115
- # headers - Hash of unencoded HTTP header key/value pairs.
131
+ # @param url [String] The optional String base URL to use as a prefix for
132
+ # all requests. Can also be the options Hash.
133
+ # @param params [Hash] Hash of URI query unencoded key/value pairs.
134
+ # @param headers [Hash] unencoded HTTP header key/value pairs.
116
135
  #
117
- # Examples
118
- #
119
- # conn.get '/items', {:page => 1}, :accept => 'application/json'
120
- # conn.head '/items/1'
136
+ # @example
137
+ # conn.get '/items', { page: 1 }, :accept => 'application/json'
121
138
  #
122
139
  # # ElasticSearch example sending a body with GET.
123
140
  # conn.get '/twitter/tweet/_search' do |req|
124
141
  # req.headers[:content_type] = 'application/json'
125
142
  # req.params[:routing] = 'kimchy'
126
- # req.body = JSON.generate(:query => {...})
143
+ # req.body = JSON.generate(query: {...})
127
144
  # end
128
145
  #
129
- # Yields a Faraday::Response for further request customizations.
130
- # Returns a Faraday::Response.
146
+ # @yield [Faraday::Request] for further request customizations
147
+ # @return [Faraday::Response]
148
+
149
+ # @!method head(url = nil, params = nil, headers = nil)
150
+ # Makes a HEAD HTTP request without a body.
151
+ # @!scope class
152
+ #
153
+ # @param url [String] The optional String base URL to use as a prefix for
154
+ # all requests. Can also be the options Hash.
155
+ # @param params [Hash] Hash of URI query unencoded key/value pairs.
156
+ # @param headers [Hash] unencoded HTTP header key/value pairs.
157
+ #
158
+ # @example
159
+ # conn.head '/items/1'
160
+ #
161
+ # @yield [Faraday::Request] for further request customizations
162
+ # @return [Faraday::Response]
163
+
164
+ # @!method delete(url = nil, params = nil, headers = nil)
165
+ # Makes a DELETE HTTP request without a body.
166
+ # @!scope class
167
+ #
168
+ # @param url [String] The optional String base URL to use as a prefix for
169
+ # all requests. Can also be the options Hash.
170
+ # @param params [Hash] Hash of URI query unencoded key/value pairs.
171
+ # @param headers [Hash] unencoded HTTP header key/value pairs.
172
+ #
173
+ # @example
174
+ # conn.delete '/items/1'
175
+ #
176
+ # @yield [Faraday::Request] for further request customizations
177
+ # @return [Faraday::Response]
178
+
179
+ # @!method trace(url = nil, params = nil, headers = nil)
180
+ # Makes a TRACE HTTP request without a body.
181
+ # @!scope class
131
182
  #
132
- # Signature
183
+ # @param url [String] The optional String base URL to use as a prefix for
184
+ # all requests. Can also be the options Hash.
185
+ # @param params [Hash] Hash of URI query unencoded key/value pairs.
186
+ # @param headers [Hash] unencoded HTTP header key/value pairs.
133
187
  #
134
- # <verb>(url = nil, params = nil, headers = nil)
188
+ # @example
189
+ # conn.connect '/items/1'
135
190
  #
136
- # verb - An HTTP verb: get, head, or delete.
137
- %w[get head delete].each do |method|
191
+ # @yield [Faraday::Request] for further request customizations
192
+ # @return [Faraday::Response]
193
+
194
+ # @!visibility private
195
+ METHODS_WITH_QUERY.each do |method|
138
196
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
139
197
  def #{method}(url = nil, params = nil, headers = nil)
140
- run_request(:#{method}, url, nil, headers) { |request|
198
+ run_request(:#{method}, url, nil, headers) do |request|
141
199
  request.params.update(params) if params
142
- yield(request) if block_given?
143
- }
200
+ yield request if block_given?
201
+ end
144
202
  end
145
203
  RUBY
146
204
  end
147
205
 
148
- # Public: Makes an HTTP request with a body.
206
+ # @overload options()
207
+ # Returns current Connection options.
208
+ #
209
+ # @overload options(url, params = nil, headers = nil)
210
+ # Makes an OPTIONS HTTP request to the given URL.
211
+ # @param url [String] String base URL to sue as a prefix for all requests.
212
+ # @param params [Hash] Hash of URI query unencoded key/value pairs.
213
+ # @param headers [Hash] unencoded HTTP header key/value pairs.
149
214
  #
150
- # url - The optional String base URL to use as a prefix for all
151
- # requests. Can also be the options Hash.
152
- # body - The String body for the request.
153
- # headers - Hash of unencoded HTTP header key/value pairs.
215
+ # @example
216
+ # conn.options '/items/1'
217
+ #
218
+ # @yield [Faraday::Request] for further request customizations
219
+ # @return [Faraday::Response]
220
+ def options(*args)
221
+ return @options if args.size.zero?
222
+
223
+ url, params, headers = *args
224
+ run_request(:options, url, nil, headers) do |request|
225
+ request.params.update(params) if params
226
+ yield request if block_given?
227
+ end
228
+ end
229
+
230
+ # @!method post(url = nil, body = nil, headers = nil)
231
+ # Makes a POST HTTP request with a body.
232
+ # @!scope class
154
233
  #
155
- # Examples
234
+ # @param url [String] The optional String base URL to use as a prefix for
235
+ # all requests. Can also be the options Hash.
236
+ # @param body [String] body for the request.
237
+ # @param headers [Hash] unencoded HTTP header key/value pairs.
156
238
  #
157
- # conn.post '/items', data, :content_type => 'application/json'
239
+ # @example
240
+ # conn.post '/items', data, content_type: 'application/json'
158
241
  #
159
242
  # # Simple ElasticSearch indexing sample.
160
243
  # conn.post '/twitter/tweet' do |req|
161
244
  # req.headers[:content_type] = 'application/json'
162
245
  # req.params[:routing] = 'kimchy'
163
- # req.body = JSON.generate(:user => 'kimchy', ...)
246
+ # req.body = JSON.generate(user: 'kimchy', ...)
164
247
  # end
165
248
  #
166
- # Yields a Faraday::Response for further request customizations.
167
- # Returns a Faraday::Response.
249
+ # @yield [Faraday::Request] for further request customizations
250
+ # @return [Faraday::Response]
251
+
252
+ # @!method put(url = nil, body = nil, headers = nil)
253
+ # Makes a PUT HTTP request with a body.
254
+ # @!scope class
168
255
  #
169
- # Signature
256
+ # @param url [String] The optional String base URL to use as a prefix for
257
+ # all requests. Can also be the options Hash.
258
+ # @param body [String] body for the request.
259
+ # @param headers [Hash] unencoded HTTP header key/value pairs.
170
260
  #
171
- # <verb>(url = nil, body = nil, headers = nil)
261
+ # @example
262
+ # # TODO: Make it a PUT example
263
+ # conn.post '/items', data, content_type: 'application/json'
172
264
  #
173
- # verb - An HTTP verb: post, put, or patch.
174
- %w[post put patch].each do |method|
265
+ # # Simple ElasticSearch indexing sample.
266
+ # conn.post '/twitter/tweet' do |req|
267
+ # req.headers[:content_type] = 'application/json'
268
+ # req.params[:routing] = 'kimchy'
269
+ # req.body = JSON.generate(user: 'kimchy', ...)
270
+ # end
271
+ #
272
+ # @yield [Faraday::Request] for further request customizations
273
+ # @return [Faraday::Response]
274
+
275
+ # @!visibility private
276
+ METHODS_WITH_BODY.each do |method|
175
277
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
176
278
  def #{method}(url = nil, body = nil, headers = nil, &block)
177
279
  run_request(:#{method}, url, body, headers, &block)
@@ -179,123 +281,126 @@ module Faraday
179
281
  RUBY
180
282
  end
181
283
 
182
- # Public: Sets up the Authorization header with these credentials, encoded
284
+ # Sets up the Authorization header with these credentials, encoded
183
285
  # with base64.
184
286
  #
185
- # login - The authentication login.
186
- # pass - The authentication password.
287
+ # @param login [String] The authentication login.
288
+ # @param pass [String] The authentication password.
187
289
  #
188
- # Examples
290
+ # @example
189
291
  #
190
292
  # conn.basic_auth 'Aladdin', 'open sesame'
191
293
  # conn.headers['Authorization']
192
294
  # # => "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="
193
295
  #
194
- # Returns nothing.
296
+ # @return [void]
195
297
  def basic_auth(login, pass)
196
298
  set_authorization_header(:basic_auth, login, pass)
197
299
  end
198
300
 
199
- # Public: Sets up the Authorization header with the given token.
301
+ # Sets up the Authorization header with the given token.
200
302
  #
201
- # token - The String token.
202
- # options - Optional Hash of extra token options.
303
+ # @param token [String]
304
+ # @param options [Hash] extra token options.
203
305
  #
204
- # Examples
306
+ # @example
205
307
  #
206
- # conn.token_auth 'abcdef', :foo => 'bar'
308
+ # conn.token_auth 'abcdef', foo: 'bar'
207
309
  # conn.headers['Authorization']
208
310
  # # => "Token token=\"abcdef\",
209
311
  # foo=\"bar\""
210
312
  #
211
- # Returns nothing.
313
+ # @return [void]
212
314
  def token_auth(token, options = nil)
213
315
  set_authorization_header(:token_auth, token, options)
214
316
  end
215
317
 
216
- # Public: Sets up a custom Authorization header.
318
+ # Sets up a custom Authorization header.
217
319
  #
218
- # type - The String authorization type.
219
- # token - The String or Hash token. A String value is taken literally, and
220
- # a Hash is encoded into comma separated key/value pairs.
320
+ # @param type [String] authorization type
321
+ # @param token [String, Hash] token. A String value is taken literally, and
322
+ # a Hash is encoded into comma-separated key/value pairs.
221
323
  #
222
- # Examples
324
+ # @example
223
325
  #
224
326
  # conn.authorization :Bearer, 'mF_9.B5f-4.1JqM'
225
327
  # conn.headers['Authorization']
226
328
  # # => "Bearer mF_9.B5f-4.1JqM"
227
329
  #
228
- # conn.authorization :Token, :token => 'abcdef', :foo => 'bar'
330
+ # conn.authorization :Token, token: 'abcdef', foo: 'bar'
229
331
  # conn.headers['Authorization']
230
332
  # # => "Token token=\"abcdef\",
231
333
  # foo=\"bar\""
232
334
  #
233
- # Returns nothing.
335
+ # @return [void]
234
336
  def authorization(type, token)
235
337
  set_authorization_header(:authorization, type, token)
236
338
  end
237
339
 
238
- # Internal: Traverse the middleware stack in search of a
239
- # parallel-capable adapter.
340
+ # Check if the adapter is parallel-capable.
240
341
  #
241
- # Yields in case of not found.
342
+ # @yield if the adapter isn't parallel-capable, or if no adapter is set yet.
242
343
  #
243
- # Returns a parallel manager or nil if not found.
344
+ # @return [Object, nil] a parallel manager or nil if yielded
345
+ # @api private
244
346
  def default_parallel_manager
245
347
  @default_parallel_manager ||= begin
246
- handler = @builder.handlers.detect do |h|
247
- h.klass.respond_to?(:supports_parallel?) and h.klass.supports_parallel?
248
- end
348
+ adapter = @builder.adapter.klass if @builder.adapter
249
349
 
250
- if handler
251
- handler.klass.setup_parallel_manager
350
+ if support_parallel?(adapter)
351
+ adapter.setup_parallel_manager
252
352
  elsif block_given?
253
353
  yield
254
354
  end
255
355
  end
256
356
  end
257
357
 
258
- # Public: Determine if this Faraday::Connection can make parallel requests.
358
+ # Determine if this Faraday::Connection can make parallel requests.
259
359
  #
260
- # Returns true or false.
360
+ # @return [Boolean]
261
361
  def in_parallel?
262
362
  !!@parallel_manager
263
363
  end
264
364
 
265
- # Public: Sets up the parallel manager to make a set of requests.
365
+ # Sets up the parallel manager to make a set of requests.
266
366
  #
267
- # manager - The parallel manager that this Connection's Adapter uses.
367
+ # @param manager [Object] The parallel manager that this Connection's
368
+ # Adapter uses.
268
369
  #
269
- # Yields a block to execute multiple requests.
270
- # Returns nothing.
370
+ # @yield a block to execute multiple requests.
371
+ # @return [void]
271
372
  def in_parallel(manager = nil)
272
- @parallel_manager = manager || default_parallel_manager {
273
- warn "Warning: `in_parallel` called but no parallel-capable adapter on Faraday stack"
274
- warn caller[2,10].join("\n")
373
+ @parallel_manager = manager || default_parallel_manager do
374
+ warn 'Warning: `in_parallel` called but no parallel-capable adapter ' \
375
+ 'on Faraday stack'
376
+ warn caller[2, 10].join("\n")
275
377
  nil
276
- }
378
+ end
277
379
  yield
278
- @parallel_manager && @parallel_manager.run
380
+ @parallel_manager&.run
279
381
  ensure
280
382
  @parallel_manager = nil
281
383
  end
282
384
 
283
- # Public: Gets or Sets the Hash proxy options.
284
- def proxy(arg = nil)
285
- return @proxy if arg.nil?
286
- @proxy = ProxyOptions.from(arg)
385
+ # Sets the Hash proxy options.
386
+ #
387
+ # @param new_value [Object]
388
+ def proxy=(new_value)
389
+ @manual_proxy = true
390
+ @proxy = new_value ? ProxyOptions.from(new_value) : nil
287
391
  end
288
392
 
289
393
  def_delegators :url_prefix, :scheme, :scheme=, :host, :host=, :port, :port=
290
394
  def_delegator :url_prefix, :path, :path_prefix
291
395
 
292
- # Public: Parses the giving url with URI and stores the individual
293
- # components in this connection. These components serve as defaults for
396
+ # Parses the given URL with URI and stores the individual
397
+ # components in this connection. These components serve as defaults for
294
398
  # requests made by this connection.
295
399
  #
296
- # url - A String or URI.
400
+ # @param url [String, URI]
401
+ # @param encoder [Object]
297
402
  #
298
- # Examples
403
+ # @example
299
404
  #
300
405
  # conn = Faraday::Connection.new { ... }
301
406
  # conn.url_prefix = "https://sushi.com/api"
@@ -303,8 +408,6 @@ module Faraday
303
408
  # conn.path_prefix # => "/api"
304
409
  #
305
410
  # conn.get("nigiri?page=2") # accesses https://sushi.com/api/nigiri
306
- #
307
- # Returns the parsed URI from teh given input..
308
411
  def url_prefix=(url, encoder = nil)
309
412
  uri = @url_prefix = Utils.URI(url)
310
413
  self.path_prefix = uri.path
@@ -316,58 +419,70 @@ module Faraday
316
419
  basic_auth user, password
317
420
  uri.user = uri.password = nil
318
421
  end
319
-
320
- uri
321
422
  end
322
423
 
323
- # Public: Sets the path prefix and ensures that it always has a leading
424
+ # Sets the path prefix and ensures that it always has a leading
324
425
  # slash.
325
426
  #
326
- # value - A String.
427
+ # @param value [String]
327
428
  #
328
- # Returns the new String path prefix.
429
+ # @return [String] the new path prefix
329
430
  def path_prefix=(value)
330
431
  url_prefix.path = if value
331
- value = '/' + value unless value[0,1] == '/'
332
- value
333
- end
432
+ value = '/' + value unless value[0, 1] == '/'
433
+ value
434
+ end
334
435
  end
335
436
 
336
- # Public: Takes a relative url for a request and combines it with the defaults
437
+ # Takes a relative url for a request and combines it with the defaults
337
438
  # set on the connection instance.
338
439
  #
440
+ # @param url [String]
441
+ # @param extra_params [Hash]
442
+ #
443
+ # @example
339
444
  # conn = Faraday::Connection.new { ... }
340
445
  # conn.url_prefix = "https://sushi.com/api?token=abc"
341
446
  # conn.scheme # => https
342
447
  # conn.path_prefix # => "/api"
343
448
  #
344
- # conn.build_url("nigiri?page=2") # => https://sushi.com/api/nigiri?token=abc&page=2
345
- # conn.build_url("nigiri", :page => 2) # => https://sushi.com/api/nigiri?token=abc&page=2
449
+ # conn.build_url("nigiri?page=2")
450
+ # # => https://sushi.com/api/nigiri?token=abc&page=2
451
+ #
452
+ # conn.build_url("nigiri", page: 2)
453
+ # # => https://sushi.com/api/nigiri?token=abc&page=2
346
454
  #
347
455
  def build_url(url = nil, extra_params = nil)
348
456
  uri = build_exclusive_url(url)
349
457
 
350
458
  query_values = params.dup.merge_query(uri.query, options.params_encoder)
351
- query_values.update extra_params if extra_params
352
- uri.query = query_values.empty? ? nil : query_values.to_query(options.params_encoder)
459
+ query_values.update(extra_params) if extra_params
460
+ uri.query =
461
+ if query_values.empty?
462
+ nil
463
+ else
464
+ query_values.to_query(options.params_encoder)
465
+ end
353
466
 
354
467
  uri
355
468
  end
356
469
 
357
470
  # Builds and runs the Faraday::Request.
358
471
  #
359
- # method - The Symbol HTTP method.
360
- # url - The String or URI to access.
361
- # body - The String body
362
- # headers - Hash of unencoded HTTP header key/value pairs.
472
+ # @param method [Symbol] HTTP method.
473
+ # @param url [String, URI] String or URI to access.
474
+ # @param body [Object] The request body that will eventually be converted to
475
+ # a string.
476
+ # @param headers [Hash] unencoded HTTP header key/value pairs.
363
477
  #
364
- # Returns a Faraday::Response.
478
+ # @return [Faraday::Response]
365
479
  def run_request(method, url, body, headers)
366
- if !METHODS.include?(method)
480
+ unless METHODS.include?(method)
367
481
  raise ArgumentError, "unknown http method: #{method}"
368
482
  end
369
483
 
370
484
  request = build_request(method) do |req|
485
+ req.options.proxy = proxy_for_request(url)
371
486
  req.url(url) if url
372
487
  req.headers.update(headers) if headers
373
488
  req.body = body if body
@@ -379,59 +494,121 @@ module Faraday
379
494
 
380
495
  # Creates and configures the request object.
381
496
  #
382
- # Returns the new Request.
497
+ # @param method [Symbol]
498
+ #
499
+ # @yield [Faraday::Request] if block given
500
+ # @return [Faraday::Request]
383
501
  def build_request(method)
384
502
  Request.create(method) do |req|
385
- req.params = self.params.dup
386
- req.headers = self.headers.dup
387
- req.options = self.options.merge(:proxy => self.proxy)
503
+ req.params = params.dup
504
+ req.headers = headers.dup
505
+ req.options = options.dup
388
506
  yield(req) if block_given?
389
507
  end
390
508
  end
391
509
 
392
- # Internal: Build an absolute URL based on url_prefix.
510
+ # Build an absolute URL based on url_prefix.
393
511
  #
394
- # url - A String or URI-like object
395
- # params - A Faraday::Utils::ParamsHash to replace the query values
512
+ # @param url [String, URI]
513
+ # @param params [Faraday::Utils::ParamsHash] A Faraday::Utils::ParamsHash to
514
+ # replace the query values
396
515
  # of the resulting url (default: nil).
397
516
  #
398
- # Returns the resulting URI instance.
517
+ # @return [URI]
399
518
  def build_exclusive_url(url = nil, params = nil, params_encoder = nil)
400
- url = nil if url.respond_to?(:empty?) and url.empty?
519
+ url = nil if url.respond_to?(:empty?) && url.empty?
401
520
  base = url_prefix
402
- if url and base.path and base.path !~ /\/$/
521
+ if url && base.path && base.path !~ %r{/$}
403
522
  base = base.dup
404
- base.path = base.path + '/' # ensure trailing slash
523
+ base.path = base.path + '/' # ensure trailing slash
405
524
  end
406
525
  uri = url ? base + url : base
407
- uri.query = params.to_query(params_encoder || options.params_encoder) if params
408
- uri.query = nil if uri.query and uri.query.empty?
526
+ if params
527
+ uri.query = params.to_query(params_encoder || options.params_encoder)
528
+ end
529
+ # rubocop:disable Style/SafeNavigation
530
+ uri.query = nil if uri.query && uri.query.empty?
531
+ # rubocop:enable Style/SafeNavigation
409
532
  uri
410
533
  end
411
534
 
412
- # Internal: Creates a duplicate of this Faraday::Connection.
535
+ # Creates a duplicate of this Faraday::Connection.
413
536
  #
414
- # Returns a Faraday::Connection.
537
+ # @api private
538
+ #
539
+ # @return [Faraday::Connection]
415
540
  def dup
416
541
  self.class.new(build_exclusive_url,
417
- :headers => headers.dup,
418
- :params => params.dup,
419
- :builder => builder.dup,
420
- :ssl => ssl.dup,
421
- :request => options.dup)
542
+ headers: headers.dup,
543
+ params: params.dup,
544
+ builder: builder.dup,
545
+ ssl: ssl.dup,
546
+ request: options.dup)
422
547
  end
423
548
 
424
- # Internal: Yields username and password extracted from a URI if they both exist.
549
+ # Yields username and password extracted from a URI if they both exist.
550
+ #
551
+ # @param uri [URI]
552
+ # @yield [username, password] any username and password
553
+ # @yieldparam username [String] any username from URI
554
+ # @yieldparam password [String] any password from URI
555
+ # @return [void]
556
+ # @api private
425
557
  def with_uri_credentials(uri)
426
- if uri.user and uri.password
427
- yield(Utils.unescape(uri.user), Utils.unescape(uri.password))
428
- end
558
+ return unless uri.user && uri.password
559
+
560
+ yield(Utils.unescape(uri.user), Utils.unescape(uri.password))
429
561
  end
430
562
 
431
563
  def set_authorization_header(header_type, *args)
432
- header = Faraday::Request.lookup_middleware(header_type).
433
- header(*args)
564
+ header = Faraday::Request
565
+ .lookup_middleware(header_type)
566
+ .header(*args)
567
+
434
568
  headers[Faraday::Request::Authorization::KEY] = header
435
569
  end
570
+
571
+ def proxy_from_env(url)
572
+ return if Faraday.ignore_env_proxy
573
+
574
+ uri = nil
575
+ if URI.parse('').respond_to?(:find_proxy)
576
+ case url
577
+ when String
578
+ uri = Utils.URI(url)
579
+ uri = URI.parse("#{uri.scheme}://#{uri.hostname}").find_proxy
580
+ when URI
581
+ uri = url.find_proxy
582
+ when nil
583
+ uri = find_default_proxy
584
+ end
585
+ else
586
+ warn 'no_proxy is unsupported' if ENV['no_proxy'] || ENV['NO_PROXY']
587
+ uri = find_default_proxy
588
+ end
589
+ ProxyOptions.from(uri) if uri
590
+ end
591
+
592
+ def find_default_proxy
593
+ uri = ENV['http_proxy']
594
+ return unless uri && !uri.empty?
595
+
596
+ uri = 'http://' + uri if uri !~ /^http/i
597
+ uri
598
+ end
599
+
600
+ def proxy_for_request(url)
601
+ return proxy if @manual_proxy
602
+
603
+ if url && Utils.URI(url).absolute?
604
+ proxy_from_env(url)
605
+ else
606
+ proxy
607
+ end
608
+ end
609
+
610
+ def support_parallel?(adapter)
611
+ adapter&.respond_to?(:supports_parallel?) && adapter&.supports_parallel?
612
+ end
436
613
  end
437
614
  end