faraday 1.4.1 → 2.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +198 -4
  3. data/LICENSE.md +1 -1
  4. data/README.md +34 -20
  5. data/Rakefile +6 -1
  6. data/examples/client_spec.rb +67 -13
  7. data/examples/client_test.rb +81 -16
  8. data/lib/faraday/adapter/test.rb +117 -52
  9. data/lib/faraday/adapter.rb +12 -20
  10. data/lib/faraday/connection.rb +86 -134
  11. data/lib/faraday/encoders/flat_params_encoder.rb +3 -2
  12. data/lib/faraday/encoders/nested_params_encoder.rb +15 -7
  13. data/lib/faraday/error.rb +65 -15
  14. data/lib/faraday/logging/formatter.rb +30 -17
  15. data/lib/faraday/middleware.rb +44 -3
  16. data/lib/faraday/middleware_registry.rb +17 -63
  17. data/lib/faraday/options/connection_options.rb +7 -6
  18. data/lib/faraday/options/env.rb +88 -65
  19. data/lib/faraday/options/proxy_options.rb +17 -6
  20. data/lib/faraday/options/request_options.rb +8 -7
  21. data/lib/faraday/options/ssl_options.rb +62 -45
  22. data/lib/faraday/options.rb +8 -7
  23. data/lib/faraday/rack_builder.rb +46 -47
  24. data/lib/faraday/request/authorization.rb +37 -38
  25. data/lib/faraday/request/instrumentation.rb +5 -1
  26. data/lib/faraday/request/json.rb +70 -0
  27. data/lib/faraday/request/url_encoded.rb +5 -1
  28. data/lib/faraday/request.rb +20 -37
  29. data/lib/faraday/response/json.rb +74 -0
  30. data/lib/faraday/response/logger.rb +13 -7
  31. data/lib/faraday/response/raise_error.rb +45 -18
  32. data/lib/faraday/response.rb +15 -21
  33. data/lib/faraday/utils/headers.rb +18 -7
  34. data/lib/faraday/utils.rb +11 -7
  35. data/lib/faraday/version.rb +1 -1
  36. data/lib/faraday.rb +12 -32
  37. data/spec/faraday/adapter/test_spec.rb +182 -0
  38. data/spec/faraday/connection_spec.rb +219 -92
  39. data/spec/faraday/error_spec.rb +122 -7
  40. data/spec/faraday/middleware_registry_spec.rb +31 -0
  41. data/spec/faraday/middleware_spec.rb +163 -2
  42. data/spec/faraday/options/env_spec.rb +8 -2
  43. data/spec/faraday/options/options_spec.rb +1 -1
  44. data/spec/faraday/options/proxy_options_spec.rb +42 -0
  45. data/spec/faraday/params_encoders/nested_spec.rb +10 -1
  46. data/spec/faraday/rack_builder_spec.rb +26 -54
  47. data/spec/faraday/request/authorization_spec.rb +54 -24
  48. data/spec/faraday/request/instrumentation_spec.rb +5 -7
  49. data/spec/faraday/request/json_spec.rb +199 -0
  50. data/spec/faraday/request/url_encoded_spec.rb +12 -2
  51. data/spec/faraday/request_spec.rb +14 -15
  52. data/spec/faraday/response/json_spec.rb +206 -0
  53. data/spec/faraday/response/logger_spec.rb +84 -5
  54. data/spec/faraday/response/raise_error_spec.rb +133 -16
  55. data/spec/faraday/response_spec.rb +10 -1
  56. data/spec/faraday/utils/headers_spec.rb +31 -4
  57. data/spec/faraday/utils_spec.rb +66 -2
  58. data/spec/faraday_spec.rb +10 -4
  59. data/spec/spec_helper.rb +6 -5
  60. data/spec/support/fake_safe_buffer.rb +1 -1
  61. data/spec/support/faraday_middleware_subclasses.rb +18 -0
  62. data/spec/support/helper_methods.rb +0 -37
  63. data/spec/support/shared_examples/adapter.rb +2 -2
  64. data/spec/support/shared_examples/request_method.rb +22 -21
  65. metadata +27 -81
  66. data/lib/faraday/adapter/em_http.rb +0 -289
  67. data/lib/faraday/adapter/em_http_ssl_patch.rb +0 -62
  68. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +0 -69
  69. data/lib/faraday/adapter/em_synchrony.rb +0 -153
  70. data/lib/faraday/adapter/httpclient.rb +0 -152
  71. data/lib/faraday/adapter/patron.rb +0 -132
  72. data/lib/faraday/adapter/rack.rb +0 -75
  73. data/lib/faraday/adapter/typhoeus.rb +0 -15
  74. data/lib/faraday/autoload.rb +0 -92
  75. data/lib/faraday/dependency_loader.rb +0 -37
  76. data/lib/faraday/file_part.rb +0 -128
  77. data/lib/faraday/param_part.rb +0 -53
  78. data/lib/faraday/request/basic_authentication.rb +0 -20
  79. data/lib/faraday/request/multipart.rb +0 -106
  80. data/lib/faraday/request/retry.rb +0 -239
  81. data/lib/faraday/request/token_authentication.rb +0 -20
  82. data/spec/faraday/adapter/em_http_spec.rb +0 -47
  83. data/spec/faraday/adapter/em_synchrony_spec.rb +0 -16
  84. data/spec/faraday/adapter/excon_spec.rb +0 -49
  85. data/spec/faraday/adapter/httpclient_spec.rb +0 -73
  86. data/spec/faraday/adapter/net_http_spec.rb +0 -64
  87. data/spec/faraday/adapter/patron_spec.rb +0 -18
  88. data/spec/faraday/adapter/rack_spec.rb +0 -8
  89. data/spec/faraday/adapter/typhoeus_spec.rb +0 -7
  90. data/spec/faraday/composite_read_io_spec.rb +0 -80
  91. data/spec/faraday/request/multipart_spec.rb +0 -302
  92. data/spec/faraday/request/retry_spec.rb +0 -242
  93. data/spec/faraday/response/middleware_spec.rb +0 -68
  94. data/spec/support/webmock_rack_app.rb +0 -68
@@ -1,10 +1,20 @@
1
1
  # frozen_string_literal: true
2
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(',').to_h { |pair| pair.split('-') }
10
+ end
11
+ end
12
+
3
13
  shared_examples 'initializer with url' do
4
14
  context 'with simple url' do
5
- let(:address) { 'http://sushi.com' }
15
+ let(:address) { 'http://httpbingo.org' }
6
16
 
7
- it { expect(subject.host).to eq('sushi.com') }
17
+ it { expect(subject.host).to eq('httpbingo.org') }
8
18
  it { expect(subject.port).to eq(80) }
9
19
  it { expect(subject.scheme).to eq('http') }
10
20
  it { expect(subject.path_prefix).to eq('/') }
@@ -12,7 +22,7 @@ shared_examples 'initializer with url' do
12
22
  end
13
23
 
14
24
  context 'with complex url' do
15
- let(:address) { 'http://sushi.com:815/fish?a=1' }
25
+ let(:address) { 'http://httpbingo.org:815/fish?a=1' }
16
26
 
17
27
  it { expect(subject.port).to eq(815) }
18
28
  it { expect(subject.path_prefix).to eq('/fish') }
@@ -31,17 +41,17 @@ shared_examples 'default connection options' do
31
41
  after { Faraday.default_connection_options = nil }
32
42
 
33
43
  it 'works with implicit url' do
34
- conn = Faraday.new 'http://sushi.com/foo'
44
+ conn = Faraday.new 'http://httpbingo.org/foo'
35
45
  expect(conn.options.timeout).to eq(10)
36
46
  end
37
47
 
38
48
  it 'works with option url' do
39
- conn = Faraday.new url: 'http://sushi.com/foo'
49
+ conn = Faraday.new url: 'http://httpbingo.org/foo'
40
50
  expect(conn.options.timeout).to eq(10)
41
51
  end
42
52
 
43
53
  it 'works with instance connection options' do
44
- conn = Faraday.new 'http://sushi.com/foo', request: { open_timeout: 1 }
54
+ conn = Faraday.new 'http://httpbingo.org/foo', request: { open_timeout: 1 }
45
55
  expect(conn.options.timeout).to eq(10)
46
56
  expect(conn.options.open_timeout).to eq(1)
47
57
  end
@@ -51,7 +61,7 @@ shared_examples 'default connection options' do
51
61
  conn.options.timeout = 1
52
62
  expect(Faraday.default_connection_options.request.timeout).to eq(10)
53
63
 
54
- other = Faraday.new url: 'https://sushi.com/foo'
64
+ other = Faraday.new url: 'https://httpbingo.org/foo'
55
65
  other.options.timeout = 1
56
66
 
57
67
  expect(Faraday.default_connection_options.request.timeout).to eq(10)
@@ -71,14 +81,14 @@ RSpec.describe Faraday::Connection do
71
81
  subject { conn }
72
82
 
73
83
  context 'with implicit url param' do
74
- # Faraday::Connection.new('http://sushi.com')
84
+ # Faraday::Connection.new('http://httpbingo.org')
75
85
  let(:url) { address }
76
86
 
77
87
  it_behaves_like 'initializer with url'
78
88
  end
79
89
 
80
90
  context 'with explicit url param' do
81
- # Faraday::Connection.new(url: 'http://sushi.com')
91
+ # Faraday::Connection.new(url: 'http://httpbingo.org')
82
92
  let(:url) { { url: address } }
83
93
 
84
94
  it_behaves_like 'initializer with url'
@@ -98,11 +108,17 @@ RSpec.describe Faraday::Connection do
98
108
  end
99
109
 
100
110
  context 'with custom params and params in url' do
101
- let(:url) { 'http://sushi.com/fish?a=1&b=2' }
111
+ let(:url) { 'http://httpbingo.org/fish?a=1&b=2' }
102
112
  let(:options) { { params: { a: 3 } } }
103
113
  it { expect(subject.params).to eq('a' => 3, 'b' => '2') }
104
114
  end
105
115
 
116
+ context 'with basic_auth in url' do
117
+ let(:url) { 'http://Aladdin:open%20sesame@httpbingo.org/fish' }
118
+
119
+ it { expect(subject.headers['Authorization']).to eq('Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==') }
120
+ end
121
+
106
122
  context 'with custom headers' do
107
123
  let(:options) { { headers: { user_agent: 'Faraday' } } }
108
124
 
@@ -115,6 +131,12 @@ RSpec.describe Faraday::Connection do
115
131
  it { expect(subject.ssl.verify?).to be_falsey }
116
132
  end
117
133
 
134
+ context 'with verify_hostname false' do
135
+ let(:options) { { ssl: { verify_hostname: false } } }
136
+
137
+ it { expect(subject.ssl.verify_hostname?).to be_falsey }
138
+ end
139
+
118
140
  context 'with empty block' do
119
141
  let(:conn) { Faraday::Connection.new {} }
120
142
 
@@ -124,8 +146,8 @@ RSpec.describe Faraday::Connection do
124
146
  context 'with block' do
125
147
  let(:conn) do
126
148
  Faraday::Connection.new(params: { 'a' => '1' }) do |faraday|
127
- faraday.adapter :net_http
128
- faraday.url_prefix = 'http://sushi.com/omnom'
149
+ faraday.adapter :test
150
+ faraday.url_prefix = 'http://httpbingo.org/omnom'
129
151
  end
130
152
  end
131
153
 
@@ -135,41 +157,22 @@ RSpec.describe Faraday::Connection do
135
157
  end
136
158
 
137
159
  describe '#close' do
160
+ before { Faraday.default_adapter = :test }
161
+ after { Faraday.default_adapter = nil }
162
+
138
163
  it 'can close underlying app' do
139
164
  expect(conn.app).to receive(:close)
140
165
  conn.close
141
166
  end
142
167
  end
143
168
 
144
- describe 'basic_auth' do
145
- subject { conn }
146
-
147
- context 'calling the #basic_auth method' do
148
- before { subject.basic_auth 'Aladdin', 'open sesame' }
149
-
150
- it { expect(subject.headers['Authorization']).to eq('Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==') }
151
- end
152
-
153
- context 'adding basic auth info to url' do
154
- let(:url) { 'http://Aladdin:open%20sesame@sushi.com/fish' }
155
-
156
- it { expect(subject.headers['Authorization']).to eq('Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==') }
157
- end
158
- end
159
-
160
- describe '#token_auth' do
161
- before { subject.token_auth('abcdef', nonce: 'abc') }
162
-
163
- it { expect(subject.headers['Authorization']).to eq('Token nonce="abc", token="abcdef"') }
164
- end
165
-
166
169
  describe '#build_exclusive_url' do
167
170
  context 'with relative path' do
168
171
  subject { conn.build_exclusive_url('sake.html') }
169
172
 
170
173
  it 'uses connection host as default host' do
171
- conn.host = 'sushi.com'
172
- expect(subject.host).to eq('sushi.com')
174
+ conn.host = 'httpbingo.org'
175
+ expect(subject.host).to eq('httpbingo.org')
173
176
  expect(subject.scheme).to eq('http')
174
177
  end
175
178
 
@@ -206,10 +209,10 @@ RSpec.describe Faraday::Connection do
206
209
  end
207
210
 
208
211
  context 'with complete url' do
209
- subject { conn.build_exclusive_url('http://sushi.com/sake.html?a=1') }
212
+ subject { conn.build_exclusive_url('http://httpbingo.org/sake.html?a=1') }
210
213
 
211
214
  it { expect(subject.scheme).to eq('http') }
212
- it { expect(subject.host).to eq('sushi.com') }
215
+ it { expect(subject.host).to eq('httpbingo.org') }
213
216
  it { expect(subject.port).to eq(80) }
214
217
  it { expect(subject.path).to eq('/sake.html') }
215
218
  it { expect(subject.query).to eq('a=1') }
@@ -217,35 +220,35 @@ RSpec.describe Faraday::Connection do
217
220
 
218
221
  it 'overrides connection port for absolute url' do
219
222
  conn.port = 23
220
- uri = conn.build_exclusive_url('http://sushi.com')
223
+ uri = conn.build_exclusive_url('http://httpbingo.org')
221
224
  expect(uri.port).to eq(80)
222
225
  end
223
226
 
224
227
  it 'does not add ending slash given nil url' do
225
- conn.url_prefix = 'http://sushi.com/nigiri'
228
+ conn.url_prefix = 'http://httpbingo.org/nigiri'
226
229
  uri = conn.build_exclusive_url
227
230
  expect(uri.path).to eq('/nigiri')
228
231
  end
229
232
 
230
233
  it 'does not add ending slash given empty url' do
231
- conn.url_prefix = 'http://sushi.com/nigiri'
234
+ conn.url_prefix = 'http://httpbingo.org/nigiri'
232
235
  uri = conn.build_exclusive_url('')
233
236
  expect(uri.path).to eq('/nigiri')
234
237
  end
235
238
 
236
239
  it 'does not use connection params' do
237
- conn.url_prefix = 'http://sushi.com/nigiri'
240
+ conn.url_prefix = 'http://httpbingo.org/nigiri'
238
241
  conn.params = { a: 1 }
239
- expect(conn.build_exclusive_url.to_s).to eq('http://sushi.com/nigiri')
242
+ expect(conn.build_exclusive_url.to_s).to eq('http://httpbingo.org/nigiri')
240
243
  end
241
244
 
242
245
  it 'allows to provide params argument' do
243
- conn.url_prefix = 'http://sushi.com/nigiri'
246
+ conn.url_prefix = 'http://httpbingo.org/nigiri'
244
247
  conn.params = { a: 1 }
245
248
  params = Faraday::Utils::ParamsHash.new
246
249
  params[:a] = 2
247
250
  uri = conn.build_exclusive_url(nil, params)
248
- expect(uri.to_s).to eq('http://sushi.com/nigiri?a=2')
251
+ expect(uri.to_s).to eq('http://httpbingo.org/nigiri?a=2')
249
252
  end
250
253
 
251
254
  it 'handles uri instances' do
@@ -253,28 +256,35 @@ RSpec.describe Faraday::Connection do
253
256
  expect(uri.path).to eq('/sake.html')
254
257
  end
255
258
 
259
+ it 'always returns new URI instance' do
260
+ conn.url_prefix = 'http://httpbingo.org'
261
+ uri1 = conn.build_exclusive_url(nil)
262
+ uri2 = conn.build_exclusive_url(nil)
263
+ expect(uri1).not_to equal(uri2)
264
+ end
265
+
256
266
  context 'with url_prefixed connection' do
257
- let(:url) { 'http://sushi.com/sushi/' }
267
+ let(:url) { 'http://httpbingo.org/get/' }
258
268
 
259
269
  it 'parses url and changes scheme' do
260
270
  conn.scheme = 'https'
261
271
  uri = conn.build_exclusive_url('sake.html')
262
- expect(uri.to_s).to eq('https://sushi.com/sushi/sake.html')
272
+ expect(uri.to_s).to eq('https://httpbingo.org/get/sake.html')
263
273
  end
264
274
 
265
275
  it 'joins url to base with ending slash' do
266
276
  uri = conn.build_exclusive_url('sake.html')
267
- expect(uri.to_s).to eq('http://sushi.com/sushi/sake.html')
277
+ expect(uri.to_s).to eq('http://httpbingo.org/get/sake.html')
268
278
  end
269
279
 
270
280
  it 'used default base with ending slash' do
271
281
  uri = conn.build_exclusive_url
272
- expect(uri.to_s).to eq('http://sushi.com/sushi/')
282
+ expect(uri.to_s).to eq('http://httpbingo.org/get/')
273
283
  end
274
284
 
275
285
  it 'overrides base' do
276
286
  uri = conn.build_exclusive_url('/sake/')
277
- expect(uri.to_s).to eq('http://sushi.com/sake/')
287
+ expect(uri.to_s).to eq('http://httpbingo.org/sake/')
278
288
  end
279
289
  end
280
290
 
@@ -290,35 +300,90 @@ RSpec.describe Faraday::Connection do
290
300
  it 'joins url to base when used relative path' do
291
301
  conn = Faraday.new(url: url)
292
302
  uri = conn.build_exclusive_url('service:search?limit=400')
293
- expect(uri.to_s).to eq('http://service.com/service%3Asearch?limit=400')
303
+ expect(uri.to_s).to eq('http://service.com/service:search?limit=400')
294
304
  end
295
305
 
296
306
  it 'joins url to base when used with path prefix' do
297
307
  conn = Faraday.new(url: url)
298
308
  conn.path_prefix = '/api'
299
309
  uri = conn.build_exclusive_url('service:search?limit=400')
300
- expect(uri.to_s).to eq('http://service.com/api/service%3Asearch?limit=400')
310
+ expect(uri.to_s).to eq('http://service.com/api/service:search?limit=400')
311
+ end
312
+ end
313
+
314
+ context 'with protocol-relative URL (GHSA-33mh-2634-fwr2)' do
315
+ it 'does not allow host override with //evil.com/path' do
316
+ conn.url_prefix = 'http://httpbingo.org/api'
317
+ uri = conn.build_exclusive_url('//evil.com/path')
318
+ expect(uri.host).to eq('httpbingo.org')
319
+ end
320
+
321
+ it 'does not allow host override with URI("//evil.com/path")' do
322
+ conn.url_prefix = 'http://httpbingo.org/api'
323
+ uri = conn.build_exclusive_url(URI('//evil.com/path?token=1'))
324
+ expect(uri.host).to eq('httpbingo.org')
325
+ expect(uri.query).to eq('token=1')
326
+ end
327
+
328
+ it 'does not allow host override with //evil.com:8080/path' do
329
+ conn.url_prefix = 'http://httpbingo.org/api'
330
+ uri = conn.build_exclusive_url('//evil.com:8080/path')
331
+ expect(uri.host).to eq('httpbingo.org')
332
+ end
333
+
334
+ it 'does not allow host override with //user:pass@evil.com/path' do
335
+ conn.url_prefix = 'http://httpbingo.org/api'
336
+ uri = conn.build_exclusive_url('//user:pass@evil.com/path')
337
+ expect(uri.host).to eq('httpbingo.org')
338
+ end
339
+
340
+ it 'does not allow host override with ///evil.com' do
341
+ conn.url_prefix = 'http://httpbingo.org/api'
342
+ uri = conn.build_exclusive_url('///evil.com')
343
+ expect(uri.host).to eq('httpbingo.org')
344
+ end
345
+
346
+ it 'still allows single-slash absolute paths' do
347
+ conn.url_prefix = 'http://httpbingo.org/api'
348
+ uri = conn.build_exclusive_url('/safe/path')
349
+ expect(uri.host).to eq('httpbingo.org')
350
+ expect(uri.path).to eq('/safe/path')
351
+ end
352
+ end
353
+
354
+ context 'with a custom `default_uri_parser`' do
355
+ let(:url) { 'http://httpbingo.org' }
356
+ let(:parser) { Addressable::URI }
357
+
358
+ around do |example|
359
+ with_default_uri_parser(parser) do
360
+ example.run
361
+ end
362
+ end
363
+
364
+ it 'does not raise error' do
365
+ expect { conn.build_exclusive_url('/nigiri') }.not_to raise_error
301
366
  end
302
367
  end
303
368
  end
304
369
 
305
370
  describe '#build_url' do
306
- let(:url) { 'http://sushi.com/nigiri' }
371
+ let(:url) { 'http://httpbingo.org/nigiri' }
307
372
 
308
373
  it 'uses params' do
309
374
  conn.params = { a: 1, b: 1 }
310
- expect(conn.build_url.to_s).to eq('http://sushi.com/nigiri?a=1&b=1')
375
+ expect(conn.build_url.to_s).to eq('http://httpbingo.org/nigiri?a=1&b=1')
311
376
  end
312
377
 
313
378
  it 'merges params' do
314
379
  conn.params = { a: 1, b: 1 }
315
380
  url = conn.build_url(nil, b: 2, c: 3)
316
- expect(url.to_s).to eq('http://sushi.com/nigiri?a=1&b=2&c=3')
381
+ expect(url.to_s).to eq('http://httpbingo.org/nigiri?a=1&b=2&c=3')
317
382
  end
318
383
  end
319
384
 
320
385
  describe '#build_request' do
321
- let(:url) { 'https://asushi.com/sake.html' }
386
+ let(:url) { 'https://ahttpbingo.org/sake.html' }
322
387
  let(:request) { conn.build_request(:get) }
323
388
 
324
389
  before do
@@ -335,7 +400,7 @@ RSpec.describe Faraday::Connection do
335
400
  describe '#to_env' do
336
401
  subject { conn.build_request(:get).to_env(conn).url }
337
402
 
338
- let(:url) { 'http://sushi.com/sake.html' }
403
+ let(:url) { 'http://httpbingo.org/sake.html' }
339
404
  let(:options) { { params: @params } }
340
405
 
341
406
  it 'parses url params into query' do
@@ -442,6 +507,14 @@ RSpec.describe Faraday::Connection do
442
507
  end
443
508
  end
444
509
 
510
+ it 'allows when url in no proxy list with url_prefix' do
511
+ with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example.com' do
512
+ conn = Faraday::Connection.new
513
+ conn.url_prefix = 'http://example.com'
514
+ expect(conn.proxy).to be_nil
515
+ end
516
+ end
517
+
445
518
  it 'allows when prefixed url is not in no proxy list' do
446
519
  with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example.com' do
447
520
  conn = Faraday::Connection.new('http://prefixedexample.com')
@@ -493,7 +566,7 @@ RSpec.describe Faraday::Connection do
493
566
  it 'uses env http_proxy' do
494
567
  with_env 'http_proxy' => 'http://proxy.com' do
495
568
  conn = Faraday.new
496
- expect(conn.instance_variable_get('@manual_proxy')).to be_falsey
569
+ expect(conn.instance_variable_get(:@manual_proxy)).to be_falsey
497
570
  expect(conn.proxy_for_request('http://google.co.uk').host).to eq('proxy.com')
498
571
  end
499
572
  end
@@ -501,7 +574,7 @@ RSpec.describe Faraday::Connection do
501
574
  it 'uses processes no_proxy before http_proxy' do
502
575
  with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'google.co.uk' do
503
576
  conn = Faraday.new
504
- expect(conn.instance_variable_get('@manual_proxy')).to be_falsey
577
+ expect(conn.instance_variable_get(:@manual_proxy)).to be_falsey
505
578
  expect(conn.proxy_for_request('http://google.co.uk')).to be_nil
506
579
  end
507
580
  end
@@ -509,7 +582,7 @@ RSpec.describe Faraday::Connection do
509
582
  it 'uses env https_proxy' do
510
583
  with_env 'https_proxy' => 'https://proxy.com' do
511
584
  conn = Faraday.new
512
- expect(conn.instance_variable_get('@manual_proxy')).to be_falsey
585
+ expect(conn.instance_variable_get(:@manual_proxy)).to be_falsey
513
586
  expect(conn.proxy_for_request('https://google.co.uk').host).to eq('proxy.com')
514
587
  end
515
588
  end
@@ -517,7 +590,7 @@ RSpec.describe Faraday::Connection do
517
590
  it 'uses processes no_proxy before https_proxy' do
518
591
  with_env 'https_proxy' => 'https://proxy.com', 'no_proxy' => 'google.co.uk' do
519
592
  conn = Faraday.new
520
- expect(conn.instance_variable_get('@manual_proxy')).to be_falsey
593
+ expect(conn.instance_variable_get(:@manual_proxy)).to be_falsey
521
594
  expect(conn.proxy_for_request('https://google.co.uk')).to be_nil
522
595
  end
523
596
  end
@@ -527,7 +600,7 @@ RSpec.describe Faraday::Connection do
527
600
  conn = Faraday.new
528
601
  conn.proxy = 'http://proxy2.com'
529
602
 
530
- expect(conn.instance_variable_get('@manual_proxy')).to be_truthy
603
+ expect(conn.instance_variable_get(:@manual_proxy)).to be_truthy
531
604
  expect(conn.proxy_for_request('https://google.co.uk').host).to eq('proxy2.com')
532
605
  end
533
606
  end
@@ -541,26 +614,32 @@ RSpec.describe Faraday::Connection do
541
614
  end
542
615
 
543
616
  context 'performing a request' do
544
- before { stub_request(:get, 'http://example.com') }
617
+ let(:url) { 'http://example.com' }
618
+ let(:conn) do
619
+ Faraday.new do |f|
620
+ f.adapter :test do |stubs|
621
+ stubs.get(url) do
622
+ [200, {}, 'ok']
623
+ end
624
+ end
625
+ end
626
+ end
545
627
 
546
628
  it 'dynamically checks proxy' do
547
629
  with_env 'http_proxy' => 'http://proxy.com:80' do
548
- conn = Faraday.new
549
630
  expect(conn.proxy.uri.host).to eq('proxy.com')
550
631
 
551
- conn.get('http://example.com') do |req|
632
+ conn.get(url) do |req|
552
633
  expect(req.options.proxy.uri.host).to eq('proxy.com')
553
634
  end
554
635
  end
555
636
 
556
- conn.get('http://example.com')
557
- expect(conn.instance_variable_get('@temp_proxy')).to be_nil
637
+ conn.get(url)
638
+ expect(conn.instance_variable_get(:@temp_proxy)).to be_nil
558
639
  end
559
640
 
560
641
  it 'dynamically check no proxy' do
561
642
  with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example.com' do
562
- conn = Faraday.new
563
-
564
643
  expect(conn.proxy.uri.host).to eq('proxy.com')
565
644
 
566
645
  conn.get('http://example.com') do |req|
@@ -574,7 +653,7 @@ RSpec.describe Faraday::Connection do
574
653
  describe '#dup' do
575
654
  subject { conn.dup }
576
655
 
577
- let(:url) { 'http://sushi.com/foo' }
656
+ let(:url) { 'http://httpbingo.org/foo' }
578
657
  let(:options) do
579
658
  {
580
659
  ssl: { verify: :none },
@@ -590,7 +669,6 @@ RSpec.describe Faraday::Connection do
590
669
 
591
670
  context 'after manual changes' do
592
671
  before do
593
- subject.basic_auth('', '')
594
672
  subject.headers['content-length'] = 12
595
673
  subject.params['b'] = '2'
596
674
  subject.options[:open_timeout] = 10
@@ -625,14 +703,42 @@ RSpec.describe Faraday::Connection do
625
703
 
626
704
  it_behaves_like 'default connection options'
627
705
  end
706
+
707
+ context 'preserving a user_agent assigned via default_conncetion_options' do
708
+ around do |example|
709
+ old = Faraday.default_connection_options
710
+ Faraday.default_connection_options = { headers: { user_agent: 'My Agent 1.2' } }
711
+ example.run
712
+ Faraday.default_connection_options = old
713
+ end
714
+
715
+ context 'when url is a Hash' do
716
+ let(:conn) { Faraday.new(url: 'http://example.co', headers: { 'CustomHeader' => 'CustomValue' }) }
717
+
718
+ it { expect(conn.headers).to eq('CustomHeader' => 'CustomValue', 'User-Agent' => 'My Agent 1.2') }
719
+ end
720
+
721
+ context 'when url is a String' do
722
+ let(:conn) { Faraday.new('http://example.co', headers: { 'CustomHeader' => 'CustomValue' }) }
723
+
724
+ it { expect(conn.headers).to eq('CustomHeader' => 'CustomValue', 'User-Agent' => 'My Agent 1.2') }
725
+ end
726
+ end
628
727
  end
629
728
 
630
729
  describe 'request params' do
631
730
  context 'with simple url' do
632
731
  let(:url) { 'http://example.com' }
633
- let!(:stubbed) { stub_request(:get, 'http://example.com?a=a&p=3') }
732
+ let(:stubs) { Faraday::Adapter::Test::Stubs.new }
634
733
 
635
- after { expect(stubbed).to have_been_made.once }
734
+ before do
735
+ conn.adapter(:test, stubs)
736
+ stubs.get('http://example.com?a=a&p=3') do
737
+ [200, {}, 'ok']
738
+ end
739
+ end
740
+
741
+ after { stubs.verify_stubbed_calls }
636
742
 
637
743
  it 'test_overrides_request_params' do
638
744
  conn.get('?p=2&a=a', p: 3)
@@ -654,15 +760,22 @@ RSpec.describe Faraday::Connection do
654
760
  context 'with url and extra params' do
655
761
  let(:url) { 'http://example.com?a=1&b=2' }
656
762
  let(:options) { { params: { c: 3 } } }
763
+ let(:stubs) { Faraday::Adapter::Test::Stubs.new }
764
+
765
+ before do
766
+ conn.adapter(:test, stubs)
767
+ end
657
768
 
658
769
  it 'merges connection and request params' do
659
- stubbed = stub_request(:get, 'http://example.com?a=1&b=2&c=3&limit=5&page=1')
770
+ expected = 'http://example.com?a=1&b=2&c=3&limit=5&page=1'
771
+ stubs.get(expected) { [200, {}, 'ok'] }
660
772
  conn.get('?page=1', limit: 5)
661
- expect(stubbed).to have_been_made.once
773
+ stubs.verify_stubbed_calls
662
774
  end
663
775
 
664
776
  it 'allows to override all params' do
665
- stubbed = stub_request(:get, 'http://example.com?b=b')
777
+ expected = 'http://example.com?b=b'
778
+ stubs.get(expected) { [200, {}, 'ok'] }
666
779
  conn.get('?p=1&a=a', p: 2) do |req|
667
780
  expect(req.params[:a]).to eq('a')
668
781
  expect(req.params['c']).to eq(3)
@@ -670,47 +783,61 @@ RSpec.describe Faraday::Connection do
670
783
  req.params = { b: 'b' }
671
784
  expect(req.params['b']).to eq('b')
672
785
  end
673
- expect(stubbed).to have_been_made.once
786
+ stubs.verify_stubbed_calls
674
787
  end
675
788
 
676
789
  it 'allows to set params_encoder for single request' do
677
- encoder = Object.new
678
- def encoder.encode(params)
679
- params.map { |k, v| "#{k.upcase}-#{v.to_s.upcase}" }.join(',')
680
- end
681
- stubbed = stub_request(:get, 'http://example.com/?A-1,B-2,C-3,FEELING-BLUE')
790
+ encoder = CustomEncoder.new
791
+ expected = 'http://example.com/?A-1,B-2,C-3,FEELING-BLUE'
792
+ stubs.get(expected) { [200, {}, 'ok'] }
682
793
 
683
- conn.get('/', feeling: 'blue') do |req|
794
+ conn.get('/', a: 1, b: 2, c: 3, feeling: 'blue') do |req|
684
795
  req.options.params_encoder = encoder
685
796
  end
686
- expect(stubbed).to have_been_made.once
797
+ stubs.verify_stubbed_calls
687
798
  end
688
799
  end
689
800
 
690
801
  context 'with default params encoder' do
691
- let!(:stubbed) { stub_request(:get, 'http://example.com?color%5B%5D=red&color%5B%5D=blue') }
692
- after { expect(stubbed).to have_been_made.once }
802
+ let(:stubs) { Faraday::Adapter::Test::Stubs.new }
803
+
804
+ before do
805
+ conn.adapter(:test, stubs)
806
+ stubs.get('http://example.com?color%5B%5D=blue&color%5B%5D=red') do
807
+ [200, {}, 'ok']
808
+ end
809
+ end
810
+
811
+ after { stubs.verify_stubbed_calls }
693
812
 
694
813
  it 'supports array params in url' do
695
- conn.get('http://example.com?color[]=red&color[]=blue')
814
+ conn.get('http://example.com?color[]=blue&color[]=red')
696
815
  end
697
816
 
698
817
  it 'supports array params in params' do
699
- conn.get('http://example.com', color: %w[red blue])
818
+ conn.get('http://example.com', color: %w[blue red])
700
819
  end
701
820
  end
702
821
 
703
822
  context 'with flat params encoder' do
704
823
  let(:options) { { request: { params_encoder: Faraday::FlatParamsEncoder } } }
705
- let!(:stubbed) { stub_request(:get, 'http://example.com?color=blue') }
706
- after { expect(stubbed).to have_been_made.once }
824
+ let(:stubs) { Faraday::Adapter::Test::Stubs.new }
825
+
826
+ before do
827
+ conn.adapter(:test, stubs)
828
+ stubs.get('http://example.com?color=blue&color=red') do
829
+ [200, {}, 'ok']
830
+ end
831
+ end
832
+
833
+ after { stubs.verify_stubbed_calls }
707
834
 
708
835
  it 'supports array params in params' do
709
- conn.get('http://example.com', color: %w[red blue])
836
+ conn.get('http://example.com', color: %w[blue red])
710
837
  end
711
838
 
712
839
  context 'with array param in url' do
713
- let(:url) { 'http://example.com?color[]=red&color[]=blue' }
840
+ let(:url) { 'http://example.com?color[]=blue&color[]=red' }
714
841
 
715
842
  it do
716
843
  conn.get('/')