faraday 0.7.4 → 1.0.1
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +276 -0
- data/LICENSE.md +1 -1
- data/README.md +40 -153
- data/Rakefile +4 -139
- data/examples/client_spec.rb +65 -0
- data/examples/client_test.rb +79 -0
- data/lib/faraday/adapter/em_http.rb +286 -0
- data/lib/faraday/adapter/em_http_ssl_patch.rb +62 -0
- data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +69 -0
- data/lib/faraday/adapter/em_synchrony.rb +120 -36
- data/lib/faraday/adapter/excon.rb +108 -12
- data/lib/faraday/adapter/httpclient.rb +152 -0
- data/lib/faraday/adapter/net_http.rb +187 -43
- data/lib/faraday/adapter/net_http_persistent.rb +91 -0
- data/lib/faraday/adapter/patron.rb +106 -10
- data/lib/faraday/adapter/rack.rb +75 -0
- data/lib/faraday/adapter/test.rb +160 -61
- data/lib/faraday/adapter/typhoeus.rb +7 -46
- data/lib/faraday/adapter.rb +105 -33
- data/lib/faraday/adapter_registry.rb +30 -0
- data/lib/faraday/autoload.rb +95 -0
- data/lib/faraday/connection.rb +525 -157
- data/lib/faraday/dependency_loader.rb +37 -0
- data/lib/faraday/encoders/flat_params_encoder.rb +98 -0
- data/lib/faraday/encoders/nested_params_encoder.rb +171 -0
- data/lib/faraday/error.rb +122 -30
- data/lib/faraday/file_part.rb +128 -0
- data/lib/faraday/logging/formatter.rb +105 -0
- data/lib/faraday/middleware.rb +14 -22
- data/lib/faraday/middleware_registry.rb +129 -0
- data/lib/faraday/options/connection_options.rb +22 -0
- data/lib/faraday/options/env.rb +181 -0
- data/lib/faraday/options/proxy_options.rb +28 -0
- data/lib/faraday/options/request_options.rb +22 -0
- data/lib/faraday/options/ssl_options.rb +59 -0
- data/lib/faraday/options.rb +222 -0
- data/lib/faraday/param_part.rb +53 -0
- data/lib/faraday/parameters.rb +5 -0
- data/lib/faraday/rack_builder.rb +248 -0
- data/lib/faraday/request/authorization.rb +55 -0
- data/lib/faraday/request/basic_authentication.rb +20 -0
- data/lib/faraday/request/instrumentation.rb +54 -0
- data/lib/faraday/request/multipart.rb +84 -48
- data/lib/faraday/request/retry.rb +239 -0
- data/lib/faraday/request/token_authentication.rb +20 -0
- data/lib/faraday/request/url_encoded.rb +46 -27
- data/lib/faraday/request.rb +112 -50
- data/lib/faraday/response/logger.rb +24 -25
- data/lib/faraday/response/raise_error.rb +40 -11
- data/lib/faraday/response.rb +44 -35
- data/lib/faraday/utils/headers.rb +139 -0
- data/lib/faraday/utils/params_hash.rb +61 -0
- data/lib/faraday/utils.rb +72 -117
- data/lib/faraday.rb +142 -64
- data/spec/external_adapters/faraday_specs_setup.rb +14 -0
- data/spec/faraday/adapter/em_http_spec.rb +47 -0
- data/spec/faraday/adapter/em_synchrony_spec.rb +16 -0
- data/spec/faraday/adapter/excon_spec.rb +49 -0
- data/spec/faraday/adapter/httpclient_spec.rb +73 -0
- data/spec/faraday/adapter/net_http_persistent_spec.rb +57 -0
- data/spec/faraday/adapter/net_http_spec.rb +64 -0
- data/spec/faraday/adapter/patron_spec.rb +18 -0
- data/spec/faraday/adapter/rack_spec.rb +8 -0
- data/spec/faraday/adapter/typhoeus_spec.rb +7 -0
- data/spec/faraday/adapter_registry_spec.rb +28 -0
- data/spec/faraday/adapter_spec.rb +55 -0
- data/spec/faraday/composite_read_io_spec.rb +80 -0
- data/spec/faraday/connection_spec.rb +691 -0
- data/spec/faraday/error_spec.rb +45 -0
- data/spec/faraday/middleware_spec.rb +26 -0
- data/spec/faraday/options/env_spec.rb +70 -0
- data/spec/faraday/options/options_spec.rb +297 -0
- data/spec/faraday/options/proxy_options_spec.rb +37 -0
- data/spec/faraday/options/request_options_spec.rb +19 -0
- data/spec/faraday/params_encoders/flat_spec.rb +34 -0
- data/spec/faraday/params_encoders/nested_spec.rb +134 -0
- data/spec/faraday/rack_builder_spec.rb +196 -0
- data/spec/faraday/request/authorization_spec.rb +88 -0
- data/spec/faraday/request/instrumentation_spec.rb +76 -0
- data/spec/faraday/request/multipart_spec.rb +274 -0
- data/spec/faraday/request/retry_spec.rb +242 -0
- data/spec/faraday/request/url_encoded_spec.rb +83 -0
- data/spec/faraday/request_spec.rb +109 -0
- data/spec/faraday/response/logger_spec.rb +220 -0
- data/spec/faraday/response/middleware_spec.rb +68 -0
- data/spec/faraday/response/raise_error_spec.rb +106 -0
- data/spec/faraday/response_spec.rb +75 -0
- data/spec/faraday/utils/headers_spec.rb +82 -0
- data/spec/faraday/utils_spec.rb +56 -0
- data/spec/faraday_spec.rb +37 -0
- data/spec/spec_helper.rb +132 -0
- data/spec/support/disabling_stub.rb +14 -0
- data/spec/support/fake_safe_buffer.rb +15 -0
- data/spec/support/helper_methods.rb +133 -0
- data/spec/support/shared_examples/adapter.rb +104 -0
- data/spec/support/shared_examples/params_encoder.rb +18 -0
- data/spec/support/shared_examples/request_method.rb +234 -0
- data/spec/support/streaming_response_checker.rb +35 -0
- data/spec/support/webmock_rack_app.rb +68 -0
- metadata +126 -126
- data/Gemfile +0 -29
- data/config.ru +0 -6
- data/faraday.gemspec +0 -92
- data/lib/faraday/adapter/action_dispatch.rb +0 -29
- data/lib/faraday/builder.rb +0 -160
- data/lib/faraday/request/json.rb +0 -35
- data/lib/faraday/upload_io.rb +0 -23
- data/test/adapters/live_test.rb +0 -205
- data/test/adapters/logger_test.rb +0 -37
- data/test/adapters/net_http_test.rb +0 -33
- data/test/adapters/test_middleware_test.rb +0 -70
- data/test/connection_test.rb +0 -254
- data/test/env_test.rb +0 -158
- data/test/helper.rb +0 -41
- data/test/live_server.rb +0 -45
- data/test/middleware_stack_test.rb +0 -118
- data/test/request_middleware_test.rb +0 -116
- data/test/response_middleware_test.rb +0 -74
data/lib/faraday/connection.rb
CHANGED
|
@@ -1,246 +1,614 @@
|
|
|
1
|
-
|
|
2
|
-
require 'set'
|
|
3
|
-
require 'base64'
|
|
1
|
+
# frozen_string_literal: true
|
|
4
2
|
|
|
5
3
|
module Faraday
|
|
4
|
+
# Connection objects manage the default properties and the middleware
|
|
5
|
+
# stack for fulfilling an HTTP request.
|
|
6
|
+
#
|
|
7
|
+
# @example
|
|
8
|
+
#
|
|
9
|
+
# conn = Faraday::Connection.new 'http://sushi.com'
|
|
10
|
+
#
|
|
11
|
+
# # GET http://sushi.com/nigiri
|
|
12
|
+
# conn.get 'nigiri'
|
|
13
|
+
# # => #<Faraday::Response>
|
|
14
|
+
#
|
|
6
15
|
class Connection
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
METHODS = Set.new [:get, :post, :put, :delete, :head, :patch, :options]
|
|
10
|
-
METHODS_WITH_BODIES = Set.new [:post, :put, :patch, :options]
|
|
11
|
-
|
|
12
|
-
attr_accessor :host, :port, :scheme, :params, :headers, :parallel_manager
|
|
13
|
-
attr_reader :path_prefix, :builder, :options, :ssl
|
|
14
|
-
|
|
15
|
-
# :url
|
|
16
|
-
# :params
|
|
17
|
-
# :headers
|
|
18
|
-
# :request
|
|
19
|
-
# :ssl
|
|
20
|
-
def initialize(url = nil, options = {})
|
|
21
|
-
if url.is_a?(Hash)
|
|
22
|
-
options = url
|
|
23
|
-
url = options[:url]
|
|
24
|
-
end
|
|
25
|
-
@headers = Utils::Headers.new
|
|
26
|
-
@params = Utils::ParamsHash.new
|
|
27
|
-
@options = options[:request] || {}
|
|
28
|
-
@ssl = options[:ssl] || {}
|
|
29
|
-
@parallel_manager = options[:parallel]
|
|
16
|
+
# A Set of allowed HTTP verbs.
|
|
17
|
+
METHODS = Set.new %i[get post put delete head patch options trace]
|
|
30
18
|
|
|
31
|
-
|
|
32
|
-
|
|
19
|
+
# @return [Hash] URI query unencoded key/value pairs.
|
|
20
|
+
attr_reader :params
|
|
33
21
|
|
|
34
|
-
|
|
35
|
-
|
|
22
|
+
# @return [Hash] unencoded HTTP header key/value pairs.
|
|
23
|
+
attr_reader :headers
|
|
36
24
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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.
|
|
27
|
+
attr_reader :url_prefix
|
|
28
|
+
|
|
29
|
+
# @return [Faraday::Builder] Builder for this Connection.
|
|
30
|
+
attr_reader :builder
|
|
31
|
+
|
|
32
|
+
# @return [Hash] SSL options.
|
|
33
|
+
attr_reader :ssl
|
|
34
|
+
|
|
35
|
+
# @return [Object] the parallel manager for this Connection.
|
|
36
|
+
attr_reader :parallel_manager
|
|
37
|
+
|
|
38
|
+
# Sets the default parallel manager for this connection.
|
|
39
|
+
attr_writer :default_parallel_manager
|
|
40
|
+
|
|
41
|
+
# @return [Hash] proxy options.
|
|
42
|
+
attr_reader :proxy
|
|
43
|
+
|
|
44
|
+
# Initializes a new Faraday::Connection.
|
|
45
|
+
#
|
|
46
|
+
# @param url [URI, String] URI or String base URL to use as a prefix for all
|
|
47
|
+
# requests (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
|
|
62
|
+
def initialize(url = nil, options = nil)
|
|
63
|
+
options = ConnectionOptions.from(options)
|
|
64
|
+
|
|
65
|
+
if url.is_a?(Hash) || url.is_a?(ConnectionOptions)
|
|
66
|
+
options = options.merge(url)
|
|
67
|
+
url = options.url
|
|
41
68
|
end
|
|
42
|
-
end
|
|
43
69
|
|
|
44
|
-
|
|
45
|
-
@
|
|
70
|
+
@parallel_manager = nil
|
|
71
|
+
@headers = Utils::Headers.new
|
|
72
|
+
@params = Utils::ParamsHash.new
|
|
73
|
+
@options = options.request
|
|
74
|
+
@ssl = options.ssl
|
|
75
|
+
@default_parallel_manager = options.parallel_manager
|
|
76
|
+
|
|
77
|
+
@builder = options.builder || begin
|
|
78
|
+
# pass an empty block to Builder so it doesn't assume default middleware
|
|
79
|
+
options.new_builder(block_given? ? proc { |b| } : nil)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
self.url_prefix = url || 'http:/'
|
|
83
|
+
|
|
84
|
+
@params.update(options.params) if options.params
|
|
85
|
+
@headers.update(options.headers) if options.headers
|
|
86
|
+
|
|
87
|
+
initialize_proxy(url, options)
|
|
88
|
+
|
|
89
|
+
yield(self) if block_given?
|
|
90
|
+
|
|
91
|
+
@headers[:user_agent] ||= "Faraday v#{VERSION}"
|
|
46
92
|
end
|
|
47
93
|
|
|
48
|
-
def
|
|
49
|
-
@
|
|
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
|
|
50
102
|
end
|
|
51
103
|
|
|
52
|
-
|
|
53
|
-
|
|
104
|
+
# Sets the Hash of URI query unencoded key/value pairs.
|
|
105
|
+
# @param hash [Hash]
|
|
106
|
+
def params=(hash)
|
|
107
|
+
@params.replace hash
|
|
54
108
|
end
|
|
55
109
|
|
|
56
|
-
|
|
57
|
-
|
|
110
|
+
# Sets the Hash of unencoded HTTP header key/value pairs.
|
|
111
|
+
# @param hash [Hash]
|
|
112
|
+
def headers=(hash)
|
|
113
|
+
@headers.replace hash
|
|
58
114
|
end
|
|
59
115
|
|
|
60
|
-
|
|
61
|
-
|
|
116
|
+
extend Forwardable
|
|
117
|
+
|
|
118
|
+
def_delegators :builder, :build, :use, :request, :response, :adapter, :app
|
|
119
|
+
|
|
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
|
|
62
125
|
end
|
|
63
126
|
|
|
64
|
-
#
|
|
127
|
+
# @!method get(url = nil, params = nil, headers = nil)
|
|
128
|
+
# Makes a GET HTTP request without a body.
|
|
129
|
+
# @!scope class
|
|
65
130
|
#
|
|
66
|
-
# The
|
|
67
|
-
#
|
|
68
|
-
#
|
|
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.
|
|
69
135
|
#
|
|
70
|
-
#
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
136
|
+
# @example
|
|
137
|
+
# conn.get '/items', { page: 1 }, :accept => 'application/json'
|
|
138
|
+
#
|
|
139
|
+
# # ElasticSearch example sending a body with GET.
|
|
140
|
+
# conn.get '/twitter/tweet/_search' do |req|
|
|
141
|
+
# req.headers[:content_type] = 'application/json'
|
|
142
|
+
# req.params[:routing] = 'kimchy'
|
|
143
|
+
# req.body = JSON.generate(query: {...})
|
|
144
|
+
# end
|
|
145
|
+
#
|
|
146
|
+
# @yield [Faraday::Request] for further request customizations
|
|
147
|
+
# @return [Faraday::Response]
|
|
82
148
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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]
|
|
87
178
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
179
|
+
# @!method trace(url = nil, params = nil, headers = nil)
|
|
180
|
+
# Makes a TRACE HTTP request without a body.
|
|
181
|
+
# @!scope class
|
|
182
|
+
#
|
|
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.
|
|
187
|
+
#
|
|
188
|
+
# @example
|
|
189
|
+
# conn.connect '/items/1'
|
|
190
|
+
#
|
|
191
|
+
# @yield [Faraday::Request] for further request customizations
|
|
192
|
+
# @return [Faraday::Response]
|
|
193
|
+
|
|
194
|
+
# @!visibility private
|
|
195
|
+
METHODS_WITH_QUERY.each do |method|
|
|
196
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
197
|
+
def #{method}(url = nil, params = nil, headers = nil)
|
|
198
|
+
run_request(:#{method}, url, nil, headers) do |request|
|
|
199
|
+
request.params.update(params) if params
|
|
200
|
+
yield request if block_given?
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
RUBY
|
|
91
204
|
end
|
|
92
205
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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.
|
|
214
|
+
#
|
|
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
|
|
96
228
|
end
|
|
97
229
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
230
|
+
# @!method post(url = nil, body = nil, headers = nil)
|
|
231
|
+
# Makes a POST HTTP request with a body.
|
|
232
|
+
# @!scope class
|
|
233
|
+
#
|
|
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.
|
|
238
|
+
#
|
|
239
|
+
# @example
|
|
240
|
+
# conn.post '/items', data, content_type: 'application/json'
|
|
241
|
+
#
|
|
242
|
+
# # Simple ElasticSearch indexing sample.
|
|
243
|
+
# conn.post '/twitter/tweet' do |req|
|
|
244
|
+
# req.headers[:content_type] = 'application/json'
|
|
245
|
+
# req.params[:routing] = 'kimchy'
|
|
246
|
+
# req.body = JSON.generate(user: 'kimchy', ...)
|
|
247
|
+
# end
|
|
248
|
+
#
|
|
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
|
|
255
|
+
#
|
|
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.
|
|
260
|
+
#
|
|
261
|
+
# @example
|
|
262
|
+
# # TODO: Make it a PUT example
|
|
263
|
+
# conn.post '/items', data, content_type: 'application/json'
|
|
264
|
+
#
|
|
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|
|
|
277
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
278
|
+
def #{method}(url = nil, body = nil, headers = nil, &block)
|
|
279
|
+
run_request(:#{method}, url, body, headers, &block)
|
|
280
|
+
end
|
|
281
|
+
RUBY
|
|
101
282
|
end
|
|
102
283
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
284
|
+
# Sets up the Authorization header with these credentials, encoded
|
|
285
|
+
# with base64.
|
|
286
|
+
#
|
|
287
|
+
# @param login [String] The authentication login.
|
|
288
|
+
# @param pass [String] The authentication password.
|
|
289
|
+
#
|
|
290
|
+
# @example
|
|
291
|
+
#
|
|
292
|
+
# conn.basic_auth 'Aladdin', 'open sesame'
|
|
293
|
+
# conn.headers['Authorization']
|
|
294
|
+
# # => "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="
|
|
295
|
+
#
|
|
296
|
+
# @return [void]
|
|
297
|
+
def basic_auth(login, pass)
|
|
298
|
+
set_authorization_header(:basic_auth, login, pass)
|
|
106
299
|
end
|
|
107
300
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
301
|
+
# Sets up the Authorization header with the given token.
|
|
302
|
+
#
|
|
303
|
+
# @param token [String]
|
|
304
|
+
# @param options [Hash] extra token options.
|
|
305
|
+
#
|
|
306
|
+
# @example
|
|
307
|
+
#
|
|
308
|
+
# conn.token_auth 'abcdef', foo: 'bar'
|
|
309
|
+
# conn.headers['Authorization']
|
|
310
|
+
# # => "Token token=\"abcdef\",
|
|
311
|
+
# foo=\"bar\""
|
|
312
|
+
#
|
|
313
|
+
# @return [void]
|
|
314
|
+
def token_auth(token, options = nil)
|
|
315
|
+
set_authorization_header(:token_auth, token, options)
|
|
111
316
|
end
|
|
112
317
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
318
|
+
# Sets up a custom Authorization header.
|
|
319
|
+
#
|
|
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.
|
|
323
|
+
#
|
|
324
|
+
# @example
|
|
325
|
+
#
|
|
326
|
+
# conn.authorization :Bearer, 'mF_9.B5f-4.1JqM'
|
|
327
|
+
# conn.headers['Authorization']
|
|
328
|
+
# # => "Bearer mF_9.B5f-4.1JqM"
|
|
329
|
+
#
|
|
330
|
+
# conn.authorization :Token, token: 'abcdef', foo: 'bar'
|
|
331
|
+
# conn.headers['Authorization']
|
|
332
|
+
# # => "Token token=\"abcdef\",
|
|
333
|
+
# foo=\"bar\""
|
|
334
|
+
#
|
|
335
|
+
# @return [void]
|
|
336
|
+
def authorization(type, token)
|
|
337
|
+
set_authorization_header(:authorization, type, token)
|
|
117
338
|
end
|
|
118
339
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
340
|
+
# Check if the adapter is parallel-capable.
|
|
341
|
+
#
|
|
342
|
+
# @yield if the adapter isn't parallel-capable, or if no adapter is set yet.
|
|
343
|
+
#
|
|
344
|
+
# @return [Object, nil] a parallel manager or nil if yielded
|
|
345
|
+
# @api private
|
|
346
|
+
def default_parallel_manager
|
|
347
|
+
@default_parallel_manager ||= begin
|
|
348
|
+
adapter = @builder.adapter.klass if @builder.adapter
|
|
349
|
+
|
|
350
|
+
if support_parallel?(adapter)
|
|
351
|
+
adapter.setup_parallel_manager
|
|
352
|
+
elsif block_given?
|
|
353
|
+
yield
|
|
354
|
+
end
|
|
123
355
|
end
|
|
124
|
-
# 21 = "Authorization: Token ".size
|
|
125
|
-
comma = ",\n#{' ' * 21}"
|
|
126
|
-
@headers['authorization'] = "Token #{values * comma}"
|
|
127
356
|
end
|
|
128
357
|
|
|
358
|
+
# Determine if this Faraday::Connection can make parallel requests.
|
|
359
|
+
#
|
|
360
|
+
# @return [Boolean]
|
|
129
361
|
def in_parallel?
|
|
130
362
|
!!@parallel_manager
|
|
131
363
|
end
|
|
132
364
|
|
|
133
|
-
|
|
134
|
-
|
|
365
|
+
# Sets up the parallel manager to make a set of requests.
|
|
366
|
+
#
|
|
367
|
+
# @param manager [Object] The parallel manager that this Connection's
|
|
368
|
+
# Adapter uses.
|
|
369
|
+
#
|
|
370
|
+
# @yield a block to execute multiple requests.
|
|
371
|
+
# @return [void]
|
|
372
|
+
def in_parallel(manager = nil)
|
|
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")
|
|
377
|
+
nil
|
|
378
|
+
end
|
|
135
379
|
yield
|
|
136
|
-
@parallel_manager
|
|
380
|
+
@parallel_manager&.run
|
|
137
381
|
ensure
|
|
138
382
|
@parallel_manager = nil
|
|
139
383
|
end
|
|
140
384
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
when URI then {:uri => arg}
|
|
148
|
-
when Hash
|
|
149
|
-
if arg[:uri] = proxy_arg_to_uri(arg[:uri])
|
|
150
|
-
arg
|
|
151
|
-
else
|
|
152
|
-
raise ArgumentError, "no :uri option."
|
|
153
|
-
end
|
|
154
|
-
end
|
|
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
|
|
155
391
|
end
|
|
156
392
|
|
|
157
|
-
|
|
158
|
-
|
|
393
|
+
def_delegators :url_prefix, :scheme, :scheme=, :host, :host=, :port, :port=
|
|
394
|
+
def_delegator :url_prefix, :path, :path_prefix
|
|
395
|
+
|
|
396
|
+
# Parses the given URL with URI and stores the individual
|
|
397
|
+
# components in this connection. These components serve as defaults for
|
|
159
398
|
# requests made by this connection.
|
|
160
399
|
#
|
|
400
|
+
# @param url [String, URI]
|
|
401
|
+
# @param encoder [Object]
|
|
402
|
+
#
|
|
403
|
+
# @example
|
|
404
|
+
#
|
|
161
405
|
# conn = Faraday::Connection.new { ... }
|
|
162
406
|
# conn.url_prefix = "https://sushi.com/api"
|
|
163
407
|
# conn.scheme # => https
|
|
164
408
|
# conn.path_prefix # => "/api"
|
|
165
409
|
#
|
|
166
410
|
# conn.get("nigiri?page=2") # accesses https://sushi.com/api/nigiri
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
uri = URI.parse(url)
|
|
170
|
-
self.scheme = uri.scheme
|
|
171
|
-
self.host = uri.host
|
|
172
|
-
self.port = uri.port
|
|
411
|
+
def url_prefix=(url, encoder = nil)
|
|
412
|
+
uri = @url_prefix = Utils.URI(url)
|
|
173
413
|
self.path_prefix = uri.path
|
|
174
414
|
|
|
175
|
-
|
|
176
|
-
|
|
415
|
+
params.merge_query(uri.query, encoder)
|
|
416
|
+
uri.query = nil
|
|
177
417
|
|
|
178
|
-
uri
|
|
418
|
+
with_uri_credentials(uri) do |user, password|
|
|
419
|
+
basic_auth user, password
|
|
420
|
+
uri.user = uri.password = nil
|
|
421
|
+
end
|
|
179
422
|
end
|
|
180
423
|
|
|
181
|
-
#
|
|
424
|
+
# Sets the path prefix and ensures that it always has a leading
|
|
425
|
+
# slash.
|
|
426
|
+
#
|
|
427
|
+
# @param value [String]
|
|
428
|
+
#
|
|
429
|
+
# @return [String] the new path prefix
|
|
182
430
|
def path_prefix=(value)
|
|
183
|
-
if value
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
@path_prefix = value
|
|
431
|
+
url_prefix.path = if value
|
|
432
|
+
value = '/' + value unless value[0, 1] == '/'
|
|
433
|
+
value
|
|
434
|
+
end
|
|
188
435
|
end
|
|
189
436
|
|
|
437
|
+
# Takes a relative url for a request and combines it with the defaults
|
|
438
|
+
# set on the connection instance.
|
|
439
|
+
#
|
|
440
|
+
# @param url [String]
|
|
441
|
+
# @param extra_params [Hash]
|
|
442
|
+
#
|
|
443
|
+
# @example
|
|
444
|
+
# conn = Faraday::Connection.new { ... }
|
|
445
|
+
# conn.url_prefix = "https://sushi.com/api?token=abc"
|
|
446
|
+
# conn.scheme # => https
|
|
447
|
+
# conn.path_prefix # => "/api"
|
|
448
|
+
#
|
|
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
|
|
454
|
+
#
|
|
455
|
+
def build_url(url = nil, extra_params = nil)
|
|
456
|
+
uri = build_exclusive_url(url)
|
|
457
|
+
|
|
458
|
+
query_values = params.dup.merge_query(uri.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
|
|
466
|
+
|
|
467
|
+
uri
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
# Builds and runs the Faraday::Request.
|
|
471
|
+
#
|
|
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.
|
|
477
|
+
#
|
|
478
|
+
# @return [Faraday::Response]
|
|
190
479
|
def run_request(method, url, body, headers)
|
|
191
|
-
|
|
480
|
+
unless METHODS.include?(method)
|
|
192
481
|
raise ArgumentError, "unknown http method: #{method}"
|
|
193
482
|
end
|
|
194
483
|
|
|
195
|
-
request =
|
|
484
|
+
request = build_request(method) do |req|
|
|
485
|
+
req.options.proxy = proxy_for_request(url)
|
|
196
486
|
req.url(url) if url
|
|
197
487
|
req.headers.update(headers) if headers
|
|
198
488
|
req.body = body if body
|
|
199
|
-
yield
|
|
489
|
+
yield(req) if block_given?
|
|
200
490
|
end
|
|
201
491
|
|
|
202
|
-
|
|
203
|
-
self.app.call(env)
|
|
492
|
+
builder.build_response(self, request)
|
|
204
493
|
end
|
|
205
494
|
|
|
206
|
-
#
|
|
207
|
-
# set on the connection instance.
|
|
495
|
+
# Creates and configures the request object.
|
|
208
496
|
#
|
|
209
|
-
#
|
|
210
|
-
# conn.url_prefix = "https://sushi.com/api?token=abc"
|
|
211
|
-
# conn.scheme # => https
|
|
212
|
-
# conn.path_prefix # => "/api"
|
|
213
|
-
#
|
|
214
|
-
# conn.build_url("nigiri?page=2") # => https://sushi.com/api/nigiri?token=abc&page=2
|
|
215
|
-
# conn.build_url("nigiri", :page => 2) # => https://sushi.com/api/nigiri?token=abc&page=2
|
|
497
|
+
# @param method [Symbol]
|
|
216
498
|
#
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
499
|
+
# @yield [Faraday::Request] if block given
|
|
500
|
+
# @return [Faraday::Request]
|
|
501
|
+
def build_request(method)
|
|
502
|
+
Request.create(method) do |req|
|
|
503
|
+
req.params = params.dup
|
|
504
|
+
req.headers = headers.dup
|
|
505
|
+
req.options = options.dup
|
|
506
|
+
yield(req) if block_given?
|
|
223
507
|
end
|
|
224
|
-
|
|
225
|
-
uri.port ||= @port
|
|
226
|
-
uri.scheme ||= @scheme
|
|
227
|
-
|
|
228
|
-
params = @params.dup.merge_query(uri.query)
|
|
229
|
-
params.update extra_params if extra_params
|
|
230
|
-
uri.query = params.empty? ? nil : params.to_query
|
|
508
|
+
end
|
|
231
509
|
|
|
510
|
+
# Build an absolute URL based on url_prefix.
|
|
511
|
+
#
|
|
512
|
+
# @param url [String, URI]
|
|
513
|
+
# @param params [Faraday::Utils::ParamsHash] A Faraday::Utils::ParamsHash to
|
|
514
|
+
# replace the query values
|
|
515
|
+
# of the resulting url (default: nil).
|
|
516
|
+
#
|
|
517
|
+
# @return [URI]
|
|
518
|
+
def build_exclusive_url(url = nil, params = nil, params_encoder = nil)
|
|
519
|
+
url = nil if url.respond_to?(:empty?) && url.empty?
|
|
520
|
+
base = url_prefix
|
|
521
|
+
if url && base.path && base.path !~ %r{/$}
|
|
522
|
+
base = base.dup
|
|
523
|
+
base.path = base.path + '/' # ensure trailing slash
|
|
524
|
+
end
|
|
525
|
+
uri = url ? base + url : base
|
|
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
|
|
232
532
|
uri
|
|
233
533
|
end
|
|
234
534
|
|
|
535
|
+
# Creates a duplicate of this Faraday::Connection.
|
|
536
|
+
#
|
|
537
|
+
# @api private
|
|
538
|
+
#
|
|
539
|
+
# @return [Faraday::Connection]
|
|
235
540
|
def dup
|
|
236
|
-
self.class.new(
|
|
541
|
+
self.class.new(build_exclusive_url,
|
|
542
|
+
headers: headers.dup,
|
|
543
|
+
params: params.dup,
|
|
544
|
+
builder: builder.dup,
|
|
545
|
+
ssl: ssl.dup,
|
|
546
|
+
request: options.dup)
|
|
547
|
+
end
|
|
548
|
+
|
|
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
|
|
557
|
+
def with_uri_credentials(uri)
|
|
558
|
+
return unless uri.user && uri.password
|
|
559
|
+
|
|
560
|
+
yield(Utils.unescape(uri.user), Utils.unescape(uri.password))
|
|
237
561
|
end
|
|
238
562
|
|
|
239
|
-
def
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
563
|
+
def set_authorization_header(header_type, *args)
|
|
564
|
+
header = Faraday::Request
|
|
565
|
+
.lookup_middleware(header_type)
|
|
566
|
+
.header(*args)
|
|
567
|
+
|
|
568
|
+
headers[Faraday::Request::Authorization::KEY] = header
|
|
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
|
|
243
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?
|
|
244
612
|
end
|
|
245
613
|
end
|
|
246
614
|
end
|