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