faraday 0.13.0 → 2.0.0

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