faraday 0.13.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +496 -0
- data/LICENSE.md +1 -1
- data/README.md +28 -328
- data/Rakefile +7 -0
- data/examples/client_spec.rb +97 -0
- data/examples/client_test.rb +118 -0
- data/lib/faraday/adapter/test.rb +127 -68
- data/lib/faraday/adapter.rb +71 -22
- data/lib/faraday/adapter_registry.rb +30 -0
- data/lib/faraday/connection.rb +314 -226
- data/lib/faraday/encoders/flat_params_encoder.rb +105 -0
- data/lib/faraday/encoders/nested_params_encoder.rb +176 -0
- data/lib/faraday/error.rb +121 -37
- data/lib/faraday/logging/formatter.rb +106 -0
- data/lib/faraday/methods.rb +6 -0
- data/lib/faraday/middleware.rb +18 -25
- data/lib/faraday/middleware_registry.rb +65 -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 +32 -0
- data/lib/faraday/options/request_options.rb +22 -0
- data/lib/faraday/options/ssl_options.rb +59 -0
- data/lib/faraday/options.rb +41 -195
- data/lib/faraday/parameters.rb +4 -196
- data/lib/faraday/rack_builder.rb +91 -74
- data/lib/faraday/request/authorization.rb +37 -29
- data/lib/faraday/request/instrumentation.rb +47 -27
- data/lib/faraday/request/json.rb +55 -0
- data/lib/faraday/request/url_encoded.rb +45 -23
- data/lib/faraday/request.rb +74 -32
- data/lib/faraday/response/json.rb +54 -0
- data/lib/faraday/response/logger.rb +22 -69
- data/lib/faraday/response/raise_error.rb +57 -14
- data/lib/faraday/response.rb +26 -33
- data/lib/faraday/utils/headers.rb +139 -0
- data/lib/faraday/utils/params_hash.rb +61 -0
- data/lib/faraday/utils.rb +47 -251
- data/lib/faraday/version.rb +5 -0
- data/lib/faraday.rb +104 -197
- data/spec/external_adapters/faraday_specs_setup.rb +14 -0
- data/spec/faraday/adapter/test_spec.rb +377 -0
- data/spec/faraday/adapter_registry_spec.rb +28 -0
- data/spec/faraday/adapter_spec.rb +55 -0
- data/spec/faraday/connection_spec.rb +787 -0
- data/spec/faraday/error_spec.rb +60 -0
- data/spec/faraday/middleware_spec.rb +52 -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 +44 -0
- data/spec/faraday/options/request_options_spec.rb +19 -0
- data/spec/faraday/params_encoders/flat_spec.rb +42 -0
- data/spec/faraday/params_encoders/nested_spec.rb +142 -0
- data/spec/faraday/rack_builder_spec.rb +302 -0
- data/spec/faraday/request/authorization_spec.rb +83 -0
- data/spec/faraday/request/instrumentation_spec.rb +74 -0
- data/spec/faraday/request/json_spec.rb +111 -0
- data/spec/faraday/request/url_encoded_spec.rb +82 -0
- data/spec/faraday/request_spec.rb +109 -0
- data/spec/faraday/response/json_spec.rb +117 -0
- data/spec/faraday/response/logger_spec.rb +220 -0
- data/spec/faraday/response/raise_error_spec.rb +172 -0
- data/spec/faraday/response_spec.rb +75 -0
- data/spec/faraday/utils/headers_spec.rb +82 -0
- data/spec/faraday/utils_spec.rb +117 -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 +96 -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 +249 -0
- data/spec/support/streaming_response_checker.rb +35 -0
- metadata +71 -34
- data/lib/faraday/adapter/em_http.rb +0 -243
- data/lib/faraday/adapter/em_http_ssl_patch.rb +0 -56
- data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +0 -66
- data/lib/faraday/adapter/em_synchrony.rb +0 -106
- data/lib/faraday/adapter/excon.rb +0 -80
- data/lib/faraday/adapter/httpclient.rb +0 -128
- data/lib/faraday/adapter/net_http.rb +0 -135
- data/lib/faraday/adapter/net_http_persistent.rb +0 -54
- data/lib/faraday/adapter/patron.rb +0 -83
- data/lib/faraday/adapter/rack.rb +0 -58
- data/lib/faraday/adapter/typhoeus.rb +0 -123
- data/lib/faraday/autoload.rb +0 -84
- data/lib/faraday/request/basic_authentication.rb +0 -13
- data/lib/faraday/request/multipart.rb +0 -68
- data/lib/faraday/request/retry.rb +0 -164
- data/lib/faraday/request/token_authentication.rb +0 -15
- data/lib/faraday/upload_io.rb +0 -67
@@ -0,0 +1,787 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CustomEncoder
|
4
|
+
def encode(params)
|
5
|
+
params.map { |k, v| "#{k.upcase}-#{v.to_s.upcase}" }.join(',')
|
6
|
+
end
|
7
|
+
|
8
|
+
def decode(params)
|
9
|
+
params.split(',').map { |pair| pair.split('-') }.to_h
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
shared_examples 'initializer with url' do
|
14
|
+
context 'with simple url' do
|
15
|
+
let(:address) { 'http://sushi.com' }
|
16
|
+
|
17
|
+
it { expect(subject.host).to eq('sushi.com') }
|
18
|
+
it { expect(subject.port).to eq(80) }
|
19
|
+
it { expect(subject.scheme).to eq('http') }
|
20
|
+
it { expect(subject.path_prefix).to eq('/') }
|
21
|
+
it { expect(subject.params).to eq({}) }
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'with complex url' do
|
25
|
+
let(:address) { 'http://sushi.com:815/fish?a=1' }
|
26
|
+
|
27
|
+
it { expect(subject.port).to eq(815) }
|
28
|
+
it { expect(subject.path_prefix).to eq('/fish') }
|
29
|
+
it { expect(subject.params).to eq('a' => '1') }
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'with IPv6 address' do
|
33
|
+
let(:address) { 'http://[::1]:85/' }
|
34
|
+
|
35
|
+
it { expect(subject.host).to eq('[::1]') }
|
36
|
+
it { expect(subject.port).to eq(85) }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
shared_examples 'default connection options' do
|
41
|
+
after { Faraday.default_connection_options = nil }
|
42
|
+
|
43
|
+
it 'works with implicit url' do
|
44
|
+
conn = Faraday.new 'http://sushi.com/foo'
|
45
|
+
expect(conn.options.timeout).to eq(10)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'works with option url' do
|
49
|
+
conn = Faraday.new url: 'http://sushi.com/foo'
|
50
|
+
expect(conn.options.timeout).to eq(10)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'works with instance connection options' do
|
54
|
+
conn = Faraday.new 'http://sushi.com/foo', request: { open_timeout: 1 }
|
55
|
+
expect(conn.options.timeout).to eq(10)
|
56
|
+
expect(conn.options.open_timeout).to eq(1)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'default connection options persist with an instance overriding' do
|
60
|
+
conn = Faraday.new 'http://nigiri.com/bar'
|
61
|
+
conn.options.timeout = 1
|
62
|
+
expect(Faraday.default_connection_options.request.timeout).to eq(10)
|
63
|
+
|
64
|
+
other = Faraday.new url: 'https://sushi.com/foo'
|
65
|
+
other.options.timeout = 1
|
66
|
+
|
67
|
+
expect(Faraday.default_connection_options.request.timeout).to eq(10)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'default connection uses default connection options' do
|
71
|
+
expect(Faraday.default_connection.options.timeout).to eq(10)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
RSpec.describe Faraday::Connection do
|
76
|
+
let(:conn) { Faraday::Connection.new(url, options) }
|
77
|
+
let(:url) { nil }
|
78
|
+
let(:options) { nil }
|
79
|
+
|
80
|
+
describe '.new' do
|
81
|
+
subject { conn }
|
82
|
+
|
83
|
+
context 'with implicit url param' do
|
84
|
+
# Faraday::Connection.new('http://sushi.com')
|
85
|
+
let(:url) { address }
|
86
|
+
|
87
|
+
it_behaves_like 'initializer with url'
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'with explicit url param' do
|
91
|
+
# Faraday::Connection.new(url: 'http://sushi.com')
|
92
|
+
let(:url) { { url: address } }
|
93
|
+
|
94
|
+
it_behaves_like 'initializer with url'
|
95
|
+
end
|
96
|
+
|
97
|
+
context 'with custom builder' do
|
98
|
+
let(:custom_builder) { Faraday::RackBuilder.new }
|
99
|
+
let(:options) { { builder: custom_builder } }
|
100
|
+
|
101
|
+
it { expect(subject.builder).to eq(custom_builder) }
|
102
|
+
end
|
103
|
+
|
104
|
+
context 'with custom params' do
|
105
|
+
let(:options) { { params: { a: 1 } } }
|
106
|
+
|
107
|
+
it { expect(subject.params).to eq('a' => 1) }
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'with custom params and params in url' do
|
111
|
+
let(:url) { 'http://sushi.com/fish?a=1&b=2' }
|
112
|
+
let(:options) { { params: { a: 3 } } }
|
113
|
+
it { expect(subject.params).to eq('a' => 3, 'b' => '2') }
|
114
|
+
end
|
115
|
+
|
116
|
+
context 'with basic_auth in url' do
|
117
|
+
let(:url) { 'http://Aladdin:open%20sesame@sushi.com/fish' }
|
118
|
+
|
119
|
+
it { expect(subject.headers['Authorization']).to eq('Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==') }
|
120
|
+
end
|
121
|
+
|
122
|
+
context 'with custom headers' do
|
123
|
+
let(:options) { { headers: { user_agent: 'Faraday' } } }
|
124
|
+
|
125
|
+
it { expect(subject.headers['User-agent']).to eq('Faraday') }
|
126
|
+
end
|
127
|
+
|
128
|
+
context 'with ssl false' do
|
129
|
+
let(:options) { { ssl: { verify: false } } }
|
130
|
+
|
131
|
+
it { expect(subject.ssl.verify?).to be_falsey }
|
132
|
+
end
|
133
|
+
|
134
|
+
context 'with empty block' do
|
135
|
+
let(:conn) { Faraday::Connection.new {} }
|
136
|
+
|
137
|
+
it { expect(conn.builder.handlers.size).to eq(0) }
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'with block' do
|
141
|
+
let(:conn) do
|
142
|
+
Faraday::Connection.new(params: { 'a' => '1' }) do |faraday|
|
143
|
+
faraday.adapter :test
|
144
|
+
faraday.url_prefix = 'http://sushi.com/omnom'
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
it { expect(conn.builder.handlers.size).to eq(0) }
|
149
|
+
it { expect(conn.path_prefix).to eq('/omnom') }
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe '#close' do
|
154
|
+
before { Faraday.default_adapter = :test }
|
155
|
+
after { Faraday.default_adapter = nil }
|
156
|
+
|
157
|
+
it 'can close underlying app' do
|
158
|
+
expect(conn.app).to receive(:close)
|
159
|
+
conn.close
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe '#build_exclusive_url' do
|
164
|
+
context 'with relative path' do
|
165
|
+
subject { conn.build_exclusive_url('sake.html') }
|
166
|
+
|
167
|
+
it 'uses connection host as default host' do
|
168
|
+
conn.host = 'sushi.com'
|
169
|
+
expect(subject.host).to eq('sushi.com')
|
170
|
+
expect(subject.scheme).to eq('http')
|
171
|
+
end
|
172
|
+
|
173
|
+
it do
|
174
|
+
conn.path_prefix = '/fish'
|
175
|
+
expect(subject.path).to eq('/fish/sake.html')
|
176
|
+
end
|
177
|
+
|
178
|
+
it do
|
179
|
+
conn.path_prefix = '/'
|
180
|
+
expect(subject.path).to eq('/sake.html')
|
181
|
+
end
|
182
|
+
|
183
|
+
it do
|
184
|
+
conn.path_prefix = 'fish'
|
185
|
+
expect(subject.path).to eq('/fish/sake.html')
|
186
|
+
end
|
187
|
+
|
188
|
+
it do
|
189
|
+
conn.path_prefix = '/fish/'
|
190
|
+
expect(subject.path).to eq('/fish/sake.html')
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
context 'with absolute path' do
|
195
|
+
subject { conn.build_exclusive_url('/sake.html') }
|
196
|
+
|
197
|
+
after { expect(subject.path).to eq('/sake.html') }
|
198
|
+
|
199
|
+
it { conn.path_prefix = '/fish' }
|
200
|
+
it { conn.path_prefix = '/' }
|
201
|
+
it { conn.path_prefix = 'fish' }
|
202
|
+
it { conn.path_prefix = '/fish/' }
|
203
|
+
end
|
204
|
+
|
205
|
+
context 'with complete url' do
|
206
|
+
subject { conn.build_exclusive_url('http://sushi.com/sake.html?a=1') }
|
207
|
+
|
208
|
+
it { expect(subject.scheme).to eq('http') }
|
209
|
+
it { expect(subject.host).to eq('sushi.com') }
|
210
|
+
it { expect(subject.port).to eq(80) }
|
211
|
+
it { expect(subject.path).to eq('/sake.html') }
|
212
|
+
it { expect(subject.query).to eq('a=1') }
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'overrides connection port for absolute url' do
|
216
|
+
conn.port = 23
|
217
|
+
uri = conn.build_exclusive_url('http://sushi.com')
|
218
|
+
expect(uri.port).to eq(80)
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'does not add ending slash given nil url' do
|
222
|
+
conn.url_prefix = 'http://sushi.com/nigiri'
|
223
|
+
uri = conn.build_exclusive_url
|
224
|
+
expect(uri.path).to eq('/nigiri')
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'does not add ending slash given empty url' do
|
228
|
+
conn.url_prefix = 'http://sushi.com/nigiri'
|
229
|
+
uri = conn.build_exclusive_url('')
|
230
|
+
expect(uri.path).to eq('/nigiri')
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'does not use connection params' do
|
234
|
+
conn.url_prefix = 'http://sushi.com/nigiri'
|
235
|
+
conn.params = { a: 1 }
|
236
|
+
expect(conn.build_exclusive_url.to_s).to eq('http://sushi.com/nigiri')
|
237
|
+
end
|
238
|
+
|
239
|
+
it 'allows to provide params argument' do
|
240
|
+
conn.url_prefix = 'http://sushi.com/nigiri'
|
241
|
+
conn.params = { a: 1 }
|
242
|
+
params = Faraday::Utils::ParamsHash.new
|
243
|
+
params[:a] = 2
|
244
|
+
uri = conn.build_exclusive_url(nil, params)
|
245
|
+
expect(uri.to_s).to eq('http://sushi.com/nigiri?a=2')
|
246
|
+
end
|
247
|
+
|
248
|
+
it 'handles uri instances' do
|
249
|
+
uri = conn.build_exclusive_url(URI('/sake.html'))
|
250
|
+
expect(uri.path).to eq('/sake.html')
|
251
|
+
end
|
252
|
+
|
253
|
+
it 'always returns new URI instance' do
|
254
|
+
conn.url_prefix = 'http://sushi.com'
|
255
|
+
uri1 = conn.build_exclusive_url(nil)
|
256
|
+
uri2 = conn.build_exclusive_url(nil)
|
257
|
+
expect(uri1).not_to equal(uri2)
|
258
|
+
end
|
259
|
+
|
260
|
+
context 'with url_prefixed connection' do
|
261
|
+
let(:url) { 'http://sushi.com/sushi/' }
|
262
|
+
|
263
|
+
it 'parses url and changes scheme' do
|
264
|
+
conn.scheme = 'https'
|
265
|
+
uri = conn.build_exclusive_url('sake.html')
|
266
|
+
expect(uri.to_s).to eq('https://sushi.com/sushi/sake.html')
|
267
|
+
end
|
268
|
+
|
269
|
+
it 'joins url to base with ending slash' do
|
270
|
+
uri = conn.build_exclusive_url('sake.html')
|
271
|
+
expect(uri.to_s).to eq('http://sushi.com/sushi/sake.html')
|
272
|
+
end
|
273
|
+
|
274
|
+
it 'used default base with ending slash' do
|
275
|
+
uri = conn.build_exclusive_url
|
276
|
+
expect(uri.to_s).to eq('http://sushi.com/sushi/')
|
277
|
+
end
|
278
|
+
|
279
|
+
it 'overrides base' do
|
280
|
+
uri = conn.build_exclusive_url('/sake/')
|
281
|
+
expect(uri.to_s).to eq('http://sushi.com/sake/')
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
context 'with colon in path' do
|
286
|
+
let(:url) { 'http://service.com' }
|
287
|
+
|
288
|
+
it 'joins url to base when used absolute path' do
|
289
|
+
conn = Faraday.new(url: url)
|
290
|
+
uri = conn.build_exclusive_url('/service:search?limit=400')
|
291
|
+
expect(uri.to_s).to eq('http://service.com/service:search?limit=400')
|
292
|
+
end
|
293
|
+
|
294
|
+
it 'joins url to base when used relative path' do
|
295
|
+
conn = Faraday.new(url: url)
|
296
|
+
uri = conn.build_exclusive_url('service:search?limit=400')
|
297
|
+
expect(uri.to_s).to eq('http://service.com/service%3Asearch?limit=400')
|
298
|
+
end
|
299
|
+
|
300
|
+
it 'joins url to base when used with path prefix' do
|
301
|
+
conn = Faraday.new(url: url)
|
302
|
+
conn.path_prefix = '/api'
|
303
|
+
uri = conn.build_exclusive_url('service:search?limit=400')
|
304
|
+
expect(uri.to_s).to eq('http://service.com/api/service%3Asearch?limit=400')
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
describe '#build_url' do
|
310
|
+
let(:url) { 'http://sushi.com/nigiri' }
|
311
|
+
|
312
|
+
it 'uses params' do
|
313
|
+
conn.params = { a: 1, b: 1 }
|
314
|
+
expect(conn.build_url.to_s).to eq('http://sushi.com/nigiri?a=1&b=1')
|
315
|
+
end
|
316
|
+
|
317
|
+
it 'merges params' do
|
318
|
+
conn.params = { a: 1, b: 1 }
|
319
|
+
url = conn.build_url(nil, b: 2, c: 3)
|
320
|
+
expect(url.to_s).to eq('http://sushi.com/nigiri?a=1&b=2&c=3')
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
describe '#build_request' do
|
325
|
+
let(:url) { 'https://asushi.com/sake.html' }
|
326
|
+
let(:request) { conn.build_request(:get) }
|
327
|
+
|
328
|
+
before do
|
329
|
+
conn.headers = { 'Authorization' => 'token abc123' }
|
330
|
+
request.headers.delete('Authorization')
|
331
|
+
end
|
332
|
+
|
333
|
+
it { expect(conn.headers.keys).to eq(['Authorization']) }
|
334
|
+
it { expect(conn.headers.include?('Authorization')).to be_truthy }
|
335
|
+
it { expect(request.headers.keys).to be_empty }
|
336
|
+
it { expect(request.headers.include?('Authorization')).to be_falsey }
|
337
|
+
end
|
338
|
+
|
339
|
+
describe '#to_env' do
|
340
|
+
subject { conn.build_request(:get).to_env(conn).url }
|
341
|
+
|
342
|
+
let(:url) { 'http://sushi.com/sake.html' }
|
343
|
+
let(:options) { { params: @params } }
|
344
|
+
|
345
|
+
it 'parses url params into query' do
|
346
|
+
@params = { 'a[b]' => '1 + 2' }
|
347
|
+
expect(subject.query).to eq('a%5Bb%5D=1+%2B+2')
|
348
|
+
end
|
349
|
+
|
350
|
+
it 'escapes per spec' do
|
351
|
+
@params = { 'a' => '1+2 foo~bar.-baz' }
|
352
|
+
expect(subject.query).to eq('a=1%2B2+foo~bar.-baz')
|
353
|
+
end
|
354
|
+
|
355
|
+
it 'bracketizes nested params in query' do
|
356
|
+
@params = { 'a' => { 'b' => 'c' } }
|
357
|
+
expect(subject.query).to eq('a%5Bb%5D=c')
|
358
|
+
end
|
359
|
+
|
360
|
+
it 'bracketizes repeated params in query' do
|
361
|
+
@params = { 'a' => [1, 2] }
|
362
|
+
expect(subject.query).to eq('a%5B%5D=1&a%5B%5D=2')
|
363
|
+
end
|
364
|
+
|
365
|
+
it 'without braketizing repeated params in query' do
|
366
|
+
@params = { 'a' => [1, 2] }
|
367
|
+
conn.options.params_encoder = Faraday::FlatParamsEncoder
|
368
|
+
expect(subject.query).to eq('a=1&a=2')
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
describe 'proxy support' do
|
373
|
+
it 'accepts string' do
|
374
|
+
with_env 'http_proxy' => 'http://env-proxy.com:80' do
|
375
|
+
conn.proxy = 'http://proxy.com'
|
376
|
+
expect(conn.proxy.host).to eq('proxy.com')
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
it 'accepts uri' do
|
381
|
+
with_env 'http_proxy' => 'http://env-proxy.com:80' do
|
382
|
+
conn.proxy = URI.parse('http://proxy.com')
|
383
|
+
expect(conn.proxy.host).to eq('proxy.com')
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
it 'accepts hash with string uri' do
|
388
|
+
with_env 'http_proxy' => 'http://env-proxy.com:80' do
|
389
|
+
conn.proxy = { uri: 'http://proxy.com', user: 'rick' }
|
390
|
+
expect(conn.proxy.host).to eq('proxy.com')
|
391
|
+
expect(conn.proxy.user).to eq('rick')
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
it 'accepts hash' do
|
396
|
+
with_env 'http_proxy' => 'http://env-proxy.com:80' do
|
397
|
+
conn.proxy = { uri: URI.parse('http://proxy.com'), user: 'rick' }
|
398
|
+
expect(conn.proxy.host).to eq('proxy.com')
|
399
|
+
expect(conn.proxy.user).to eq('rick')
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
it 'accepts http env' do
|
404
|
+
with_env 'http_proxy' => 'http://env-proxy.com:80' do
|
405
|
+
expect(conn.proxy.host).to eq('env-proxy.com')
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
it 'accepts http env with auth' do
|
410
|
+
with_env 'http_proxy' => 'http://a%40b:my%20pass@proxy.com:80' do
|
411
|
+
expect(conn.proxy.user).to eq('a@b')
|
412
|
+
expect(conn.proxy.password).to eq('my pass')
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
it 'accepts env without scheme' do
|
417
|
+
with_env 'http_proxy' => 'localhost:8888' do
|
418
|
+
uri = conn.proxy[:uri]
|
419
|
+
expect(uri.host).to eq('localhost')
|
420
|
+
expect(uri.port).to eq(8888)
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
it 'fetches no proxy from nil env' do
|
425
|
+
with_env 'http_proxy' => nil do
|
426
|
+
expect(conn.proxy).to be_nil
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
430
|
+
it 'fetches no proxy from blank env' do
|
431
|
+
with_env 'http_proxy' => '' do
|
432
|
+
expect(conn.proxy).to be_nil
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
it 'does not accept uppercase env' do
|
437
|
+
with_env 'HTTP_PROXY' => 'http://localhost:8888/' do
|
438
|
+
expect(conn.proxy).to be_nil
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
442
|
+
it 'allows when url in no proxy list' do
|
443
|
+
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example.com' do
|
444
|
+
conn = Faraday::Connection.new('http://example.com')
|
445
|
+
expect(conn.proxy).to be_nil
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
it 'allows when url in no proxy list with url_prefix' do
|
450
|
+
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example.com' do
|
451
|
+
conn = Faraday::Connection.new
|
452
|
+
conn.url_prefix = 'http://example.com'
|
453
|
+
expect(conn.proxy).to be_nil
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
457
|
+
it 'allows when prefixed url is not in no proxy list' do
|
458
|
+
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example.com' do
|
459
|
+
conn = Faraday::Connection.new('http://prefixedexample.com')
|
460
|
+
expect(conn.proxy.host).to eq('proxy.com')
|
461
|
+
end
|
462
|
+
end
|
463
|
+
|
464
|
+
it 'allows when subdomain url is in no proxy list' do
|
465
|
+
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example.com' do
|
466
|
+
conn = Faraday::Connection.new('http://subdomain.example.com')
|
467
|
+
expect(conn.proxy).to be_nil
|
468
|
+
end
|
469
|
+
end
|
470
|
+
|
471
|
+
it 'allows when url not in no proxy list' do
|
472
|
+
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example2.com' do
|
473
|
+
conn = Faraday::Connection.new('http://example.com')
|
474
|
+
expect(conn.proxy.host).to eq('proxy.com')
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
it 'allows when ip address is not in no proxy list but url is' do
|
479
|
+
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'localhost' do
|
480
|
+
conn = Faraday::Connection.new('http://127.0.0.1')
|
481
|
+
expect(conn.proxy).to be_nil
|
482
|
+
end
|
483
|
+
end
|
484
|
+
|
485
|
+
it 'allows when url is not in no proxy list but ip address is' do
|
486
|
+
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => '127.0.0.1' do
|
487
|
+
conn = Faraday::Connection.new('http://localhost')
|
488
|
+
expect(conn.proxy).to be_nil
|
489
|
+
end
|
490
|
+
end
|
491
|
+
|
492
|
+
it 'allows in multi element no proxy list' do
|
493
|
+
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example0.com,example.com,example1.com' do
|
494
|
+
expect(Faraday::Connection.new('http://example0.com').proxy).to be_nil
|
495
|
+
expect(Faraday::Connection.new('http://example.com').proxy).to be_nil
|
496
|
+
expect(Faraday::Connection.new('http://example1.com').proxy).to be_nil
|
497
|
+
expect(Faraday::Connection.new('http://example2.com').proxy.host).to eq('proxy.com')
|
498
|
+
end
|
499
|
+
end
|
500
|
+
|
501
|
+
it 'test proxy requires uri' do
|
502
|
+
expect { conn.proxy = { uri: :bad_uri, user: 'rick' } }.to raise_error(ArgumentError)
|
503
|
+
end
|
504
|
+
|
505
|
+
it 'uses env http_proxy' do
|
506
|
+
with_env 'http_proxy' => 'http://proxy.com' do
|
507
|
+
conn = Faraday.new
|
508
|
+
expect(conn.instance_variable_get('@manual_proxy')).to be_falsey
|
509
|
+
expect(conn.proxy_for_request('http://google.co.uk').host).to eq('proxy.com')
|
510
|
+
end
|
511
|
+
end
|
512
|
+
|
513
|
+
it 'uses processes no_proxy before http_proxy' do
|
514
|
+
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'google.co.uk' do
|
515
|
+
conn = Faraday.new
|
516
|
+
expect(conn.instance_variable_get('@manual_proxy')).to be_falsey
|
517
|
+
expect(conn.proxy_for_request('http://google.co.uk')).to be_nil
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
it 'uses env https_proxy' do
|
522
|
+
with_env 'https_proxy' => 'https://proxy.com' do
|
523
|
+
conn = Faraday.new
|
524
|
+
expect(conn.instance_variable_get('@manual_proxy')).to be_falsey
|
525
|
+
expect(conn.proxy_for_request('https://google.co.uk').host).to eq('proxy.com')
|
526
|
+
end
|
527
|
+
end
|
528
|
+
|
529
|
+
it 'uses processes no_proxy before https_proxy' do
|
530
|
+
with_env 'https_proxy' => 'https://proxy.com', 'no_proxy' => 'google.co.uk' do
|
531
|
+
conn = Faraday.new
|
532
|
+
expect(conn.instance_variable_get('@manual_proxy')).to be_falsey
|
533
|
+
expect(conn.proxy_for_request('https://google.co.uk')).to be_nil
|
534
|
+
end
|
535
|
+
end
|
536
|
+
|
537
|
+
it 'gives priority to manually set proxy' do
|
538
|
+
with_env 'https_proxy' => 'https://proxy.com', 'no_proxy' => 'google.co.uk' do
|
539
|
+
conn = Faraday.new
|
540
|
+
conn.proxy = 'http://proxy2.com'
|
541
|
+
|
542
|
+
expect(conn.instance_variable_get('@manual_proxy')).to be_truthy
|
543
|
+
expect(conn.proxy_for_request('https://google.co.uk').host).to eq('proxy2.com')
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
547
|
+
it 'ignores env proxy if set that way' do
|
548
|
+
with_env_proxy_disabled do
|
549
|
+
with_env 'http_proxy' => 'http://duncan.proxy.com:80' do
|
550
|
+
expect(conn.proxy).to be_nil
|
551
|
+
end
|
552
|
+
end
|
553
|
+
end
|
554
|
+
|
555
|
+
context 'performing a request' do
|
556
|
+
let(:url) { 'http://example.com' }
|
557
|
+
let(:conn) do
|
558
|
+
Faraday.new do |f|
|
559
|
+
f.adapter :test do |stubs|
|
560
|
+
stubs.get(url) do
|
561
|
+
[200, {}, 'ok']
|
562
|
+
end
|
563
|
+
end
|
564
|
+
end
|
565
|
+
end
|
566
|
+
|
567
|
+
it 'dynamically checks proxy' do
|
568
|
+
with_env 'http_proxy' => 'http://proxy.com:80' do
|
569
|
+
expect(conn.proxy.uri.host).to eq('proxy.com')
|
570
|
+
|
571
|
+
conn.get(url) do |req|
|
572
|
+
expect(req.options.proxy.uri.host).to eq('proxy.com')
|
573
|
+
end
|
574
|
+
end
|
575
|
+
|
576
|
+
conn.get(url)
|
577
|
+
expect(conn.instance_variable_get('@temp_proxy')).to be_nil
|
578
|
+
end
|
579
|
+
|
580
|
+
it 'dynamically check no proxy' do
|
581
|
+
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example.com' do
|
582
|
+
expect(conn.proxy.uri.host).to eq('proxy.com')
|
583
|
+
|
584
|
+
conn.get('http://example.com') do |req|
|
585
|
+
expect(req.options.proxy).to be_nil
|
586
|
+
end
|
587
|
+
end
|
588
|
+
end
|
589
|
+
end
|
590
|
+
end
|
591
|
+
|
592
|
+
describe '#dup' do
|
593
|
+
subject { conn.dup }
|
594
|
+
|
595
|
+
let(:url) { 'http://sushi.com/foo' }
|
596
|
+
let(:options) do
|
597
|
+
{
|
598
|
+
ssl: { verify: :none },
|
599
|
+
headers: { 'content-type' => 'text/plain' },
|
600
|
+
params: { 'a' => '1' },
|
601
|
+
request: { timeout: 5 }
|
602
|
+
}
|
603
|
+
end
|
604
|
+
|
605
|
+
it { expect(subject.build_exclusive_url).to eq(conn.build_exclusive_url) }
|
606
|
+
it { expect(subject.headers['content-type']).to eq('text/plain') }
|
607
|
+
it { expect(subject.params['a']).to eq('1') }
|
608
|
+
|
609
|
+
context 'after manual changes' do
|
610
|
+
before do
|
611
|
+
subject.headers['content-length'] = 12
|
612
|
+
subject.params['b'] = '2'
|
613
|
+
subject.options[:open_timeout] = 10
|
614
|
+
end
|
615
|
+
|
616
|
+
it { expect(subject.builder.handlers.size).to eq(1) }
|
617
|
+
it { expect(conn.builder.handlers.size).to eq(1) }
|
618
|
+
it { expect(conn.headers.key?('content-length')).to be_falsey }
|
619
|
+
it { expect(conn.params.key?('b')).to be_falsey }
|
620
|
+
it { expect(subject.options[:timeout]).to eq(5) }
|
621
|
+
it { expect(conn.options[:open_timeout]).to be_nil }
|
622
|
+
end
|
623
|
+
end
|
624
|
+
|
625
|
+
describe '#respond_to?' do
|
626
|
+
it { expect(Faraday.respond_to?(:get)).to be_truthy }
|
627
|
+
it { expect(Faraday.respond_to?(:post)).to be_truthy }
|
628
|
+
end
|
629
|
+
|
630
|
+
describe 'default_connection_options' do
|
631
|
+
context 'assigning a default value' do
|
632
|
+
before do
|
633
|
+
Faraday.default_connection_options = nil
|
634
|
+
Faraday.default_connection_options.request.timeout = 10
|
635
|
+
end
|
636
|
+
|
637
|
+
it_behaves_like 'default connection options'
|
638
|
+
end
|
639
|
+
|
640
|
+
context 'assigning a hash' do
|
641
|
+
before { Faraday.default_connection_options = { request: { timeout: 10 } } }
|
642
|
+
|
643
|
+
it_behaves_like 'default connection options'
|
644
|
+
end
|
645
|
+
|
646
|
+
context 'preserving a user_agent assigned via default_conncetion_options' do
|
647
|
+
around do |example|
|
648
|
+
old = Faraday.default_connection_options
|
649
|
+
Faraday.default_connection_options = { headers: { user_agent: 'My Agent 1.2' } }
|
650
|
+
example.run
|
651
|
+
Faraday.default_connection_options = old
|
652
|
+
end
|
653
|
+
|
654
|
+
context 'when url is a Hash' do
|
655
|
+
let(:conn) { Faraday.new(url: 'http://example.co', headers: { 'CustomHeader' => 'CustomValue' }) }
|
656
|
+
|
657
|
+
it { expect(conn.headers).to eq('CustomHeader' => 'CustomValue', 'User-Agent' => 'My Agent 1.2') }
|
658
|
+
end
|
659
|
+
|
660
|
+
context 'when url is a String' do
|
661
|
+
let(:conn) { Faraday.new('http://example.co', headers: { 'CustomHeader' => 'CustomValue' }) }
|
662
|
+
|
663
|
+
it { expect(conn.headers).to eq('CustomHeader' => 'CustomValue', 'User-Agent' => 'My Agent 1.2') }
|
664
|
+
end
|
665
|
+
end
|
666
|
+
end
|
667
|
+
|
668
|
+
describe 'request params' do
|
669
|
+
context 'with simple url' do
|
670
|
+
let(:url) { 'http://example.com' }
|
671
|
+
let(:stubs) { Faraday::Adapter::Test::Stubs.new }
|
672
|
+
|
673
|
+
before do
|
674
|
+
conn.adapter(:test, stubs)
|
675
|
+
stubs.get('http://example.com?a=a&p=3') do
|
676
|
+
[200, {}, 'ok']
|
677
|
+
end
|
678
|
+
end
|
679
|
+
|
680
|
+
after { stubs.verify_stubbed_calls }
|
681
|
+
|
682
|
+
it 'test_overrides_request_params' do
|
683
|
+
conn.get('?p=2&a=a', p: 3)
|
684
|
+
end
|
685
|
+
|
686
|
+
it 'test_overrides_request_params_block' do
|
687
|
+
conn.get('?p=1&a=a', p: 2) do |req|
|
688
|
+
req.params[:p] = 3
|
689
|
+
end
|
690
|
+
end
|
691
|
+
|
692
|
+
it 'test_overrides_request_params_block_url' do
|
693
|
+
conn.get(nil, p: 2) do |req|
|
694
|
+
req.url('?p=1&a=a', 'p' => 3)
|
695
|
+
end
|
696
|
+
end
|
697
|
+
end
|
698
|
+
|
699
|
+
context 'with url and extra params' do
|
700
|
+
let(:url) { 'http://example.com?a=1&b=2' }
|
701
|
+
let(:options) { { params: { c: 3 } } }
|
702
|
+
let(:stubs) { Faraday::Adapter::Test::Stubs.new }
|
703
|
+
|
704
|
+
before do
|
705
|
+
conn.adapter(:test, stubs)
|
706
|
+
end
|
707
|
+
|
708
|
+
it 'merges connection and request params' do
|
709
|
+
expected = 'http://example.com?a=1&b=2&c=3&limit=5&page=1'
|
710
|
+
stubs.get(expected) { [200, {}, 'ok'] }
|
711
|
+
conn.get('?page=1', limit: 5)
|
712
|
+
stubs.verify_stubbed_calls
|
713
|
+
end
|
714
|
+
|
715
|
+
it 'allows to override all params' do
|
716
|
+
expected = 'http://example.com?b=b'
|
717
|
+
stubs.get(expected) { [200, {}, 'ok'] }
|
718
|
+
conn.get('?p=1&a=a', p: 2) do |req|
|
719
|
+
expect(req.params[:a]).to eq('a')
|
720
|
+
expect(req.params['c']).to eq(3)
|
721
|
+
expect(req.params['p']).to eq(2)
|
722
|
+
req.params = { b: 'b' }
|
723
|
+
expect(req.params['b']).to eq('b')
|
724
|
+
end
|
725
|
+
stubs.verify_stubbed_calls
|
726
|
+
end
|
727
|
+
|
728
|
+
it 'allows to set params_encoder for single request' do
|
729
|
+
encoder = CustomEncoder.new
|
730
|
+
expected = 'http://example.com/?A-1,B-2,C-3,FEELING-BLUE'
|
731
|
+
stubs.get(expected) { [200, {}, 'ok'] }
|
732
|
+
|
733
|
+
conn.get('/', a: 1, b: 2, c: 3, feeling: 'blue') do |req|
|
734
|
+
req.options.params_encoder = encoder
|
735
|
+
end
|
736
|
+
stubs.verify_stubbed_calls
|
737
|
+
end
|
738
|
+
end
|
739
|
+
|
740
|
+
context 'with default params encoder' do
|
741
|
+
let(:stubs) { Faraday::Adapter::Test::Stubs.new }
|
742
|
+
|
743
|
+
before do
|
744
|
+
conn.adapter(:test, stubs)
|
745
|
+
stubs.get('http://example.com?color%5B%5D=blue&color%5B%5D=red') do
|
746
|
+
[200, {}, 'ok']
|
747
|
+
end
|
748
|
+
end
|
749
|
+
|
750
|
+
after { stubs.verify_stubbed_calls }
|
751
|
+
|
752
|
+
it 'supports array params in url' do
|
753
|
+
conn.get('http://example.com?color[]=blue&color[]=red')
|
754
|
+
end
|
755
|
+
|
756
|
+
it 'supports array params in params' do
|
757
|
+
conn.get('http://example.com', color: %w[blue red])
|
758
|
+
end
|
759
|
+
end
|
760
|
+
|
761
|
+
context 'with flat params encoder' do
|
762
|
+
let(:options) { { request: { params_encoder: Faraday::FlatParamsEncoder } } }
|
763
|
+
let(:stubs) { Faraday::Adapter::Test::Stubs.new }
|
764
|
+
|
765
|
+
before do
|
766
|
+
conn.adapter(:test, stubs)
|
767
|
+
stubs.get('http://example.com?color=blue&color=red') do
|
768
|
+
[200, {}, 'ok']
|
769
|
+
end
|
770
|
+
end
|
771
|
+
|
772
|
+
after { stubs.verify_stubbed_calls }
|
773
|
+
|
774
|
+
it 'supports array params in params' do
|
775
|
+
conn.get('http://example.com', color: %w[blue red])
|
776
|
+
end
|
777
|
+
|
778
|
+
context 'with array param in url' do
|
779
|
+
let(:url) { 'http://example.com?color[]=blue&color[]=red' }
|
780
|
+
|
781
|
+
it do
|
782
|
+
conn.get('/')
|
783
|
+
end
|
784
|
+
end
|
785
|
+
end
|
786
|
+
end
|
787
|
+
end
|