faraday 1.1.0 → 2.7.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +299 -1
  3. data/LICENSE.md +1 -1
  4. data/README.md +18 -17
  5. data/examples/client_spec.rb +67 -13
  6. data/examples/client_test.rb +80 -15
  7. data/lib/faraday/adapter/test.rb +117 -52
  8. data/lib/faraday/adapter.rb +5 -20
  9. data/lib/faraday/connection.rb +64 -118
  10. data/lib/faraday/encoders/nested_params_encoder.rb +13 -6
  11. data/lib/faraday/error.rb +15 -8
  12. data/lib/faraday/logging/formatter.rb +19 -2
  13. data/lib/faraday/methods.rb +6 -0
  14. data/lib/faraday/middleware.rb +17 -5
  15. data/lib/faraday/middleware_registry.rb +17 -63
  16. data/lib/faraday/options/env.rb +31 -7
  17. data/lib/faraday/options/proxy_options.rb +4 -0
  18. data/lib/faraday/options/ssl_options.rb +11 -1
  19. data/lib/faraday/options.rb +3 -3
  20. data/lib/faraday/rack_builder.rb +23 -20
  21. data/lib/faraday/request/authorization.rb +37 -38
  22. data/lib/faraday/request/instrumentation.rb +2 -0
  23. data/lib/faraday/request/json.rb +55 -0
  24. data/lib/faraday/request/url_encoded.rb +5 -1
  25. data/lib/faraday/request.rb +12 -32
  26. data/lib/faraday/response/json.rb +54 -0
  27. data/lib/faraday/response/logger.rb +8 -4
  28. data/lib/faraday/response/raise_error.rb +9 -1
  29. data/lib/faraday/response.rb +10 -26
  30. data/lib/faraday/utils/headers.rb +7 -2
  31. data/lib/faraday/utils.rb +10 -5
  32. data/lib/faraday/version.rb +5 -0
  33. data/lib/faraday.rb +49 -58
  34. data/spec/faraday/adapter/test_spec.rb +182 -0
  35. data/spec/faraday/connection_spec.rb +207 -90
  36. data/spec/faraday/error_spec.rb +15 -0
  37. data/spec/faraday/middleware_registry_spec.rb +31 -0
  38. data/spec/faraday/middleware_spec.rb +50 -6
  39. data/spec/faraday/options/env_spec.rb +8 -2
  40. data/spec/faraday/options/proxy_options_spec.rb +7 -0
  41. data/spec/faraday/params_encoders/nested_spec.rb +8 -0
  42. data/spec/faraday/rack_builder_spec.rb +26 -54
  43. data/spec/faraday/request/authorization_spec.rb +54 -24
  44. data/spec/faraday/request/instrumentation_spec.rb +5 -7
  45. data/spec/faraday/request/json_spec.rb +111 -0
  46. data/spec/faraday/request/url_encoded_spec.rb +12 -2
  47. data/spec/faraday/request_spec.rb +5 -15
  48. data/spec/faraday/response/json_spec.rb +117 -0
  49. data/spec/faraday/response/logger_spec.rb +28 -0
  50. data/spec/faraday/response/raise_error_spec.rb +37 -4
  51. data/spec/faraday/response_spec.rb +3 -1
  52. data/spec/faraday/utils/headers_spec.rb +22 -4
  53. data/spec/faraday/utils_spec.rb +63 -1
  54. data/spec/support/fake_safe_buffer.rb +1 -1
  55. data/spec/support/helper_methods.rb +0 -37
  56. data/spec/support/shared_examples/adapter.rb +4 -3
  57. data/spec/support/shared_examples/request_method.rb +58 -29
  58. metadata +19 -45
  59. data/lib/faraday/adapter/em_http.rb +0 -286
  60. data/lib/faraday/adapter/em_http_ssl_patch.rb +0 -62
  61. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +0 -69
  62. data/lib/faraday/adapter/em_synchrony.rb +0 -150
  63. data/lib/faraday/adapter/excon.rb +0 -124
  64. data/lib/faraday/adapter/httpclient.rb +0 -152
  65. data/lib/faraday/adapter/net_http.rb +0 -219
  66. data/lib/faraday/adapter/net_http_persistent.rb +0 -91
  67. data/lib/faraday/adapter/patron.rb +0 -132
  68. data/lib/faraday/adapter/rack.rb +0 -75
  69. data/lib/faraday/adapter/typhoeus.rb +0 -15
  70. data/lib/faraday/autoload.rb +0 -95
  71. data/lib/faraday/dependency_loader.rb +0 -39
  72. data/lib/faraday/file_part.rb +0 -128
  73. data/lib/faraday/param_part.rb +0 -53
  74. data/lib/faraday/request/basic_authentication.rb +0 -20
  75. data/lib/faraday/request/multipart.rb +0 -106
  76. data/lib/faraday/request/retry.rb +0 -239
  77. data/lib/faraday/request/token_authentication.rb +0 -20
  78. data/spec/faraday/adapter/em_http_spec.rb +0 -47
  79. data/spec/faraday/adapter/em_synchrony_spec.rb +0 -16
  80. data/spec/faraday/adapter/excon_spec.rb +0 -49
  81. data/spec/faraday/adapter/httpclient_spec.rb +0 -73
  82. data/spec/faraday/adapter/net_http_persistent_spec.rb +0 -57
  83. data/spec/faraday/adapter/net_http_spec.rb +0 -64
  84. data/spec/faraday/adapter/patron_spec.rb +0 -18
  85. data/spec/faraday/adapter/rack_spec.rb +0 -8
  86. data/spec/faraday/adapter/typhoeus_spec.rb +0 -7
  87. data/spec/faraday/composite_read_io_spec.rb +0 -80
  88. data/spec/faraday/request/multipart_spec.rb +0 -302
  89. data/spec/faraday/request/retry_spec.rb +0 -242
  90. data/spec/faraday/response/middleware_spec.rb +0 -68
  91. 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,29 +22,36 @@ 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') }
19
29
  it { expect(subject.params).to eq('a' => '1') }
20
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
21
38
  end
22
39
 
23
40
  shared_examples 'default connection options' do
24
41
  after { Faraday.default_connection_options = nil }
25
42
 
26
43
  it 'works with implicit url' do
27
- conn = Faraday.new 'http://sushi.com/foo'
44
+ conn = Faraday.new 'http://httpbingo.org/foo'
28
45
  expect(conn.options.timeout).to eq(10)
29
46
  end
30
47
 
31
48
  it 'works with option url' do
32
- conn = Faraday.new url: 'http://sushi.com/foo'
49
+ conn = Faraday.new url: 'http://httpbingo.org/foo'
33
50
  expect(conn.options.timeout).to eq(10)
34
51
  end
35
52
 
36
53
  it 'works with instance connection options' do
37
- conn = Faraday.new 'http://sushi.com/foo', request: { open_timeout: 1 }
54
+ conn = Faraday.new 'http://httpbingo.org/foo', request: { open_timeout: 1 }
38
55
  expect(conn.options.timeout).to eq(10)
39
56
  expect(conn.options.open_timeout).to eq(1)
40
57
  end
@@ -44,7 +61,7 @@ shared_examples 'default connection options' do
44
61
  conn.options.timeout = 1
45
62
  expect(Faraday.default_connection_options.request.timeout).to eq(10)
46
63
 
47
- other = Faraday.new url: 'https://sushi.com/foo'
64
+ other = Faraday.new url: 'https://httpbingo.org/foo'
48
65
  other.options.timeout = 1
49
66
 
50
67
  expect(Faraday.default_connection_options.request.timeout).to eq(10)
@@ -64,14 +81,14 @@ RSpec.describe Faraday::Connection do
64
81
  subject { conn }
65
82
 
66
83
  context 'with implicit url param' do
67
- # Faraday::Connection.new('http://sushi.com')
84
+ # Faraday::Connection.new('http://httpbingo.org')
68
85
  let(:url) { address }
69
86
 
70
87
  it_behaves_like 'initializer with url'
71
88
  end
72
89
 
73
90
  context 'with explicit url param' do
74
- # Faraday::Connection.new(url: 'http://sushi.com')
91
+ # Faraday::Connection.new(url: 'http://httpbingo.org')
75
92
  let(:url) { { url: address } }
76
93
 
77
94
  it_behaves_like 'initializer with url'
@@ -91,11 +108,17 @@ RSpec.describe Faraday::Connection do
91
108
  end
92
109
 
93
110
  context 'with custom params and params in url' do
94
- let(:url) { 'http://sushi.com/fish?a=1&b=2' }
111
+ let(:url) { 'http://httpbingo.org/fish?a=1&b=2' }
95
112
  let(:options) { { params: { a: 3 } } }
96
113
  it { expect(subject.params).to eq('a' => 3, 'b' => '2') }
97
114
  end
98
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
+
99
122
  context 'with custom headers' do
100
123
  let(:options) { { headers: { user_agent: 'Faraday' } } }
101
124
 
@@ -108,6 +131,12 @@ RSpec.describe Faraday::Connection do
108
131
  it { expect(subject.ssl.verify?).to be_falsey }
109
132
  end
110
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
+
111
140
  context 'with empty block' do
112
141
  let(:conn) { Faraday::Connection.new {} }
113
142
 
@@ -117,8 +146,8 @@ RSpec.describe Faraday::Connection do
117
146
  context 'with block' do
118
147
  let(:conn) do
119
148
  Faraday::Connection.new(params: { 'a' => '1' }) do |faraday|
120
- faraday.adapter :net_http
121
- faraday.url_prefix = 'http://sushi.com/omnom'
149
+ faraday.adapter :test
150
+ faraday.url_prefix = 'http://httpbingo.org/omnom'
122
151
  end
123
152
  end
124
153
 
@@ -128,41 +157,22 @@ RSpec.describe Faraday::Connection do
128
157
  end
129
158
 
130
159
  describe '#close' do
160
+ before { Faraday.default_adapter = :test }
161
+ after { Faraday.default_adapter = nil }
162
+
131
163
  it 'can close underlying app' do
132
164
  expect(conn.app).to receive(:close)
133
165
  conn.close
134
166
  end
135
167
  end
136
168
 
137
- describe 'basic_auth' do
138
- subject { conn }
139
-
140
- context 'calling the #basic_auth method' do
141
- before { subject.basic_auth 'Aladdin', 'open sesame' }
142
-
143
- it { expect(subject.headers['Authorization']).to eq('Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==') }
144
- end
145
-
146
- context 'adding basic auth info to url' do
147
- let(:url) { 'http://Aladdin:open%20sesame@sushi.com/fish' }
148
-
149
- it { expect(subject.headers['Authorization']).to eq('Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==') }
150
- end
151
- end
152
-
153
- describe '#token_auth' do
154
- before { subject.token_auth('abcdef', nonce: 'abc') }
155
-
156
- it { expect(subject.headers['Authorization']).to eq('Token nonce="abc", token="abcdef"') }
157
- end
158
-
159
169
  describe '#build_exclusive_url' do
160
170
  context 'with relative path' do
161
171
  subject { conn.build_exclusive_url('sake.html') }
162
172
 
163
173
  it 'uses connection host as default host' do
164
- conn.host = 'sushi.com'
165
- expect(subject.host).to eq('sushi.com')
174
+ conn.host = 'httpbingo.org'
175
+ expect(subject.host).to eq('httpbingo.org')
166
176
  expect(subject.scheme).to eq('http')
167
177
  end
168
178
 
@@ -199,10 +209,10 @@ RSpec.describe Faraday::Connection do
199
209
  end
200
210
 
201
211
  context 'with complete url' do
202
- 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') }
203
213
 
204
214
  it { expect(subject.scheme).to eq('http') }
205
- it { expect(subject.host).to eq('sushi.com') }
215
+ it { expect(subject.host).to eq('httpbingo.org') }
206
216
  it { expect(subject.port).to eq(80) }
207
217
  it { expect(subject.path).to eq('/sake.html') }
208
218
  it { expect(subject.query).to eq('a=1') }
@@ -210,35 +220,35 @@ RSpec.describe Faraday::Connection do
210
220
 
211
221
  it 'overrides connection port for absolute url' do
212
222
  conn.port = 23
213
- uri = conn.build_exclusive_url('http://sushi.com')
223
+ uri = conn.build_exclusive_url('http://httpbingo.org')
214
224
  expect(uri.port).to eq(80)
215
225
  end
216
226
 
217
227
  it 'does not add ending slash given nil url' do
218
- conn.url_prefix = 'http://sushi.com/nigiri'
228
+ conn.url_prefix = 'http://httpbingo.org/nigiri'
219
229
  uri = conn.build_exclusive_url
220
230
  expect(uri.path).to eq('/nigiri')
221
231
  end
222
232
 
223
233
  it 'does not add ending slash given empty url' do
224
- conn.url_prefix = 'http://sushi.com/nigiri'
234
+ conn.url_prefix = 'http://httpbingo.org/nigiri'
225
235
  uri = conn.build_exclusive_url('')
226
236
  expect(uri.path).to eq('/nigiri')
227
237
  end
228
238
 
229
239
  it 'does not use connection params' do
230
- conn.url_prefix = 'http://sushi.com/nigiri'
240
+ conn.url_prefix = 'http://httpbingo.org/nigiri'
231
241
  conn.params = { a: 1 }
232
- 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')
233
243
  end
234
244
 
235
245
  it 'allows to provide params argument' do
236
- conn.url_prefix = 'http://sushi.com/nigiri'
246
+ conn.url_prefix = 'http://httpbingo.org/nigiri'
237
247
  conn.params = { a: 1 }
238
248
  params = Faraday::Utils::ParamsHash.new
239
249
  params[:a] = 2
240
250
  uri = conn.build_exclusive_url(nil, params)
241
- 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')
242
252
  end
243
253
 
244
254
  it 'handles uri instances' do
@@ -246,49 +256,94 @@ RSpec.describe Faraday::Connection do
246
256
  expect(uri.path).to eq('/sake.html')
247
257
  end
248
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
+
249
266
  context 'with url_prefixed connection' do
250
- let(:url) { 'http://sushi.com/sushi/' }
267
+ let(:url) { 'http://httpbingo.org/get/' }
251
268
 
252
269
  it 'parses url and changes scheme' do
253
270
  conn.scheme = 'https'
254
271
  uri = conn.build_exclusive_url('sake.html')
255
- 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')
256
273
  end
257
274
 
258
275
  it 'joins url to base with ending slash' do
259
276
  uri = conn.build_exclusive_url('sake.html')
260
- 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')
261
278
  end
262
279
 
263
280
  it 'used default base with ending slash' do
264
281
  uri = conn.build_exclusive_url
265
- expect(uri.to_s).to eq('http://sushi.com/sushi/')
282
+ expect(uri.to_s).to eq('http://httpbingo.org/get/')
266
283
  end
267
284
 
268
285
  it 'overrides base' do
269
286
  uri = conn.build_exclusive_url('/sake/')
270
- expect(uri.to_s).to eq('http://sushi.com/sake/')
287
+ expect(uri.to_s).to eq('http://httpbingo.org/sake/')
288
+ end
289
+ end
290
+
291
+ context 'with colon in path' do
292
+ let(:url) { 'http://service.com' }
293
+
294
+ it 'joins url to base when used absolute 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:search?limit=400')
298
+ end
299
+
300
+ it 'joins url to base when used relative path' do
301
+ conn = Faraday.new(url: url)
302
+ uri = conn.build_exclusive_url('service:search?limit=400')
303
+ expect(uri.to_s).to eq('http://service.com/service%3Asearch?limit=400')
304
+ end
305
+
306
+ it 'joins url to base when used with path prefix' do
307
+ conn = Faraday.new(url: url)
308
+ conn.path_prefix = '/api'
309
+ uri = conn.build_exclusive_url('service:search?limit=400')
310
+ expect(uri.to_s).to eq('http://service.com/api/service%3Asearch?limit=400')
311
+ end
312
+ end
313
+
314
+ context 'with a custom `default_uri_parser`' do
315
+ let(:url) { 'http://httpbingo.org' }
316
+ let(:parser) { Addressable::URI }
317
+
318
+ around do |example|
319
+ with_default_uri_parser(parser) do
320
+ example.run
321
+ end
322
+ end
323
+
324
+ it 'does not raise error' do
325
+ expect { conn.build_exclusive_url('/nigiri') }.not_to raise_error
271
326
  end
272
327
  end
273
328
  end
274
329
 
275
330
  describe '#build_url' do
276
- let(:url) { 'http://sushi.com/nigiri' }
331
+ let(:url) { 'http://httpbingo.org/nigiri' }
277
332
 
278
333
  it 'uses params' do
279
334
  conn.params = { a: 1, b: 1 }
280
- expect(conn.build_url.to_s).to eq('http://sushi.com/nigiri?a=1&b=1')
335
+ expect(conn.build_url.to_s).to eq('http://httpbingo.org/nigiri?a=1&b=1')
281
336
  end
282
337
 
283
338
  it 'merges params' do
284
339
  conn.params = { a: 1, b: 1 }
285
340
  url = conn.build_url(nil, b: 2, c: 3)
286
- expect(url.to_s).to eq('http://sushi.com/nigiri?a=1&b=2&c=3')
341
+ expect(url.to_s).to eq('http://httpbingo.org/nigiri?a=1&b=2&c=3')
287
342
  end
288
343
  end
289
344
 
290
345
  describe '#build_request' do
291
- let(:url) { 'https://asushi.com/sake.html' }
346
+ let(:url) { 'https://ahttpbingo.org/sake.html' }
292
347
  let(:request) { conn.build_request(:get) }
293
348
 
294
349
  before do
@@ -305,7 +360,7 @@ RSpec.describe Faraday::Connection do
305
360
  describe '#to_env' do
306
361
  subject { conn.build_request(:get).to_env(conn).url }
307
362
 
308
- let(:url) { 'http://sushi.com/sake.html' }
363
+ let(:url) { 'http://httpbingo.org/sake.html' }
309
364
  let(:options) { { params: @params } }
310
365
 
311
366
  it 'parses url params into query' do
@@ -412,6 +467,14 @@ RSpec.describe Faraday::Connection do
412
467
  end
413
468
  end
414
469
 
470
+ it 'allows when url in no proxy list with url_prefix' do
471
+ with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example.com' do
472
+ conn = Faraday::Connection.new
473
+ conn.url_prefix = 'http://example.com'
474
+ expect(conn.proxy).to be_nil
475
+ end
476
+ end
477
+
415
478
  it 'allows when prefixed url is not in no proxy list' do
416
479
  with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example.com' do
417
480
  conn = Faraday::Connection.new('http://prefixedexample.com')
@@ -463,7 +526,7 @@ RSpec.describe Faraday::Connection do
463
526
  it 'uses env http_proxy' do
464
527
  with_env 'http_proxy' => 'http://proxy.com' do
465
528
  conn = Faraday.new
466
- expect(conn.instance_variable_get('@manual_proxy')).to be_falsey
529
+ expect(conn.instance_variable_get(:@manual_proxy)).to be_falsey
467
530
  expect(conn.proxy_for_request('http://google.co.uk').host).to eq('proxy.com')
468
531
  end
469
532
  end
@@ -471,7 +534,7 @@ RSpec.describe Faraday::Connection do
471
534
  it 'uses processes no_proxy before http_proxy' do
472
535
  with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'google.co.uk' do
473
536
  conn = Faraday.new
474
- expect(conn.instance_variable_get('@manual_proxy')).to be_falsey
537
+ expect(conn.instance_variable_get(:@manual_proxy)).to be_falsey
475
538
  expect(conn.proxy_for_request('http://google.co.uk')).to be_nil
476
539
  end
477
540
  end
@@ -479,7 +542,7 @@ RSpec.describe Faraday::Connection do
479
542
  it 'uses env https_proxy' do
480
543
  with_env 'https_proxy' => 'https://proxy.com' do
481
544
  conn = Faraday.new
482
- expect(conn.instance_variable_get('@manual_proxy')).to be_falsey
545
+ expect(conn.instance_variable_get(:@manual_proxy)).to be_falsey
483
546
  expect(conn.proxy_for_request('https://google.co.uk').host).to eq('proxy.com')
484
547
  end
485
548
  end
@@ -487,7 +550,7 @@ RSpec.describe Faraday::Connection do
487
550
  it 'uses processes no_proxy before https_proxy' do
488
551
  with_env 'https_proxy' => 'https://proxy.com', 'no_proxy' => 'google.co.uk' do
489
552
  conn = Faraday.new
490
- expect(conn.instance_variable_get('@manual_proxy')).to be_falsey
553
+ expect(conn.instance_variable_get(:@manual_proxy)).to be_falsey
491
554
  expect(conn.proxy_for_request('https://google.co.uk')).to be_nil
492
555
  end
493
556
  end
@@ -497,7 +560,7 @@ RSpec.describe Faraday::Connection do
497
560
  conn = Faraday.new
498
561
  conn.proxy = 'http://proxy2.com'
499
562
 
500
- expect(conn.instance_variable_get('@manual_proxy')).to be_truthy
563
+ expect(conn.instance_variable_get(:@manual_proxy)).to be_truthy
501
564
  expect(conn.proxy_for_request('https://google.co.uk').host).to eq('proxy2.com')
502
565
  end
503
566
  end
@@ -511,26 +574,32 @@ RSpec.describe Faraday::Connection do
511
574
  end
512
575
 
513
576
  context 'performing a request' do
514
- before { stub_request(:get, 'http://example.com') }
577
+ let(:url) { 'http://example.com' }
578
+ let(:conn) do
579
+ Faraday.new do |f|
580
+ f.adapter :test do |stubs|
581
+ stubs.get(url) do
582
+ [200, {}, 'ok']
583
+ end
584
+ end
585
+ end
586
+ end
515
587
 
516
588
  it 'dynamically checks proxy' do
517
589
  with_env 'http_proxy' => 'http://proxy.com:80' do
518
- conn = Faraday.new
519
590
  expect(conn.proxy.uri.host).to eq('proxy.com')
520
591
 
521
- conn.get('http://example.com') do |req|
592
+ conn.get(url) do |req|
522
593
  expect(req.options.proxy.uri.host).to eq('proxy.com')
523
594
  end
524
595
  end
525
596
 
526
- conn.get('http://example.com')
527
- expect(conn.instance_variable_get('@temp_proxy')).to be_nil
597
+ conn.get(url)
598
+ expect(conn.instance_variable_get(:@temp_proxy)).to be_nil
528
599
  end
529
600
 
530
601
  it 'dynamically check no proxy' do
531
602
  with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example.com' do
532
- conn = Faraday.new
533
-
534
603
  expect(conn.proxy.uri.host).to eq('proxy.com')
535
604
 
536
605
  conn.get('http://example.com') do |req|
@@ -544,7 +613,7 @@ RSpec.describe Faraday::Connection do
544
613
  describe '#dup' do
545
614
  subject { conn.dup }
546
615
 
547
- let(:url) { 'http://sushi.com/foo' }
616
+ let(:url) { 'http://httpbingo.org/foo' }
548
617
  let(:options) do
549
618
  {
550
619
  ssl: { verify: :none },
@@ -560,7 +629,6 @@ RSpec.describe Faraday::Connection do
560
629
 
561
630
  context 'after manual changes' do
562
631
  before do
563
- subject.basic_auth('', '')
564
632
  subject.headers['content-length'] = 12
565
633
  subject.params['b'] = '2'
566
634
  subject.options[:open_timeout] = 10
@@ -595,14 +663,42 @@ RSpec.describe Faraday::Connection do
595
663
 
596
664
  it_behaves_like 'default connection options'
597
665
  end
666
+
667
+ context 'preserving a user_agent assigned via default_conncetion_options' do
668
+ around do |example|
669
+ old = Faraday.default_connection_options
670
+ Faraday.default_connection_options = { headers: { user_agent: 'My Agent 1.2' } }
671
+ example.run
672
+ Faraday.default_connection_options = old
673
+ end
674
+
675
+ context 'when url is a Hash' do
676
+ let(:conn) { Faraday.new(url: 'http://example.co', headers: { 'CustomHeader' => 'CustomValue' }) }
677
+
678
+ it { expect(conn.headers).to eq('CustomHeader' => 'CustomValue', 'User-Agent' => 'My Agent 1.2') }
679
+ end
680
+
681
+ context 'when url is a String' do
682
+ let(:conn) { Faraday.new('http://example.co', headers: { 'CustomHeader' => 'CustomValue' }) }
683
+
684
+ it { expect(conn.headers).to eq('CustomHeader' => 'CustomValue', 'User-Agent' => 'My Agent 1.2') }
685
+ end
686
+ end
598
687
  end
599
688
 
600
689
  describe 'request params' do
601
690
  context 'with simple url' do
602
691
  let(:url) { 'http://example.com' }
603
- let!(:stubbed) { stub_request(:get, 'http://example.com?a=a&p=3') }
692
+ let(:stubs) { Faraday::Adapter::Test::Stubs.new }
604
693
 
605
- after { expect(stubbed).to have_been_made.once }
694
+ before do
695
+ conn.adapter(:test, stubs)
696
+ stubs.get('http://example.com?a=a&p=3') do
697
+ [200, {}, 'ok']
698
+ end
699
+ end
700
+
701
+ after { stubs.verify_stubbed_calls }
606
702
 
607
703
  it 'test_overrides_request_params' do
608
704
  conn.get('?p=2&a=a', p: 3)
@@ -624,15 +720,22 @@ RSpec.describe Faraday::Connection do
624
720
  context 'with url and extra params' do
625
721
  let(:url) { 'http://example.com?a=1&b=2' }
626
722
  let(:options) { { params: { c: 3 } } }
723
+ let(:stubs) { Faraday::Adapter::Test::Stubs.new }
724
+
725
+ before do
726
+ conn.adapter(:test, stubs)
727
+ end
627
728
 
628
729
  it 'merges connection and request params' do
629
- stubbed = stub_request(:get, 'http://example.com?a=1&b=2&c=3&limit=5&page=1')
730
+ expected = 'http://example.com?a=1&b=2&c=3&limit=5&page=1'
731
+ stubs.get(expected) { [200, {}, 'ok'] }
630
732
  conn.get('?page=1', limit: 5)
631
- expect(stubbed).to have_been_made.once
733
+ stubs.verify_stubbed_calls
632
734
  end
633
735
 
634
736
  it 'allows to override all params' do
635
- stubbed = stub_request(:get, 'http://example.com?b=b')
737
+ expected = 'http://example.com?b=b'
738
+ stubs.get(expected) { [200, {}, 'ok'] }
636
739
  conn.get('?p=1&a=a', p: 2) do |req|
637
740
  expect(req.params[:a]).to eq('a')
638
741
  expect(req.params['c']).to eq(3)
@@ -640,47 +743,61 @@ RSpec.describe Faraday::Connection do
640
743
  req.params = { b: 'b' }
641
744
  expect(req.params['b']).to eq('b')
642
745
  end
643
- expect(stubbed).to have_been_made.once
746
+ stubs.verify_stubbed_calls
644
747
  end
645
748
 
646
749
  it 'allows to set params_encoder for single request' do
647
- encoder = Object.new
648
- def encoder.encode(params)
649
- params.map { |k, v| "#{k.upcase}-#{v.to_s.upcase}" }.join(',')
650
- end
651
- stubbed = stub_request(:get, 'http://example.com/?A-1,B-2,C-3,FEELING-BLUE')
750
+ encoder = CustomEncoder.new
751
+ expected = 'http://example.com/?A-1,B-2,C-3,FEELING-BLUE'
752
+ stubs.get(expected) { [200, {}, 'ok'] }
652
753
 
653
- conn.get('/', feeling: 'blue') do |req|
754
+ conn.get('/', a: 1, b: 2, c: 3, feeling: 'blue') do |req|
654
755
  req.options.params_encoder = encoder
655
756
  end
656
- expect(stubbed).to have_been_made.once
757
+ stubs.verify_stubbed_calls
657
758
  end
658
759
  end
659
760
 
660
761
  context 'with default params encoder' do
661
- let!(:stubbed) { stub_request(:get, 'http://example.com?color%5B%5D=red&color%5B%5D=blue') }
662
- after { expect(stubbed).to have_been_made.once }
762
+ let(:stubs) { Faraday::Adapter::Test::Stubs.new }
763
+
764
+ before do
765
+ conn.adapter(:test, stubs)
766
+ stubs.get('http://example.com?color%5B%5D=blue&color%5B%5D=red') do
767
+ [200, {}, 'ok']
768
+ end
769
+ end
770
+
771
+ after { stubs.verify_stubbed_calls }
663
772
 
664
773
  it 'supports array params in url' do
665
- conn.get('http://example.com?color[]=red&color[]=blue')
774
+ conn.get('http://example.com?color[]=blue&color[]=red')
666
775
  end
667
776
 
668
777
  it 'supports array params in params' do
669
- conn.get('http://example.com', color: %w[red blue])
778
+ conn.get('http://example.com', color: %w[blue red])
670
779
  end
671
780
  end
672
781
 
673
782
  context 'with flat params encoder' do
674
783
  let(:options) { { request: { params_encoder: Faraday::FlatParamsEncoder } } }
675
- let!(:stubbed) { stub_request(:get, 'http://example.com?color=blue') }
676
- after { expect(stubbed).to have_been_made.once }
784
+ let(:stubs) { Faraday::Adapter::Test::Stubs.new }
785
+
786
+ before do
787
+ conn.adapter(:test, stubs)
788
+ stubs.get('http://example.com?color=blue&color=red') do
789
+ [200, {}, 'ok']
790
+ end
791
+ end
792
+
793
+ after { stubs.verify_stubbed_calls }
677
794
 
678
795
  it 'supports array params in params' do
679
- conn.get('http://example.com', color: %w[red blue])
796
+ conn.get('http://example.com', color: %w[blue red])
680
797
  end
681
798
 
682
799
  context 'with array param in url' do
683
- let(:url) { 'http://example.com?color[]=red&color[]=blue' }
800
+ let(:url) { 'http://example.com?color[]=blue&color[]=red' }
684
801
 
685
802
  it do
686
803
  conn.get('/')
@@ -13,6 +13,7 @@ RSpec.describe Faraday::ClientError do
13
13
  it { expect(subject.message).to eq(exception.message) }
14
14
  it { expect(subject.backtrace).to eq(exception.backtrace) }
15
15
  it { expect(subject.inspect).to eq('#<Faraday::ClientError wrapped=#<RuntimeError: test>>') }
16
+ it { expect(subject.response_status).to be_nil }
16
17
  end
17
18
 
18
19
  context 'with response hash' do
@@ -22,6 +23,7 @@ RSpec.describe Faraday::ClientError do
22
23
  it { expect(subject.response).to eq(exception) }
23
24
  it { expect(subject.message).to eq('the server responded with status 400') }
24
25
  it { expect(subject.inspect).to eq('#<Faraday::ClientError response={:status=>400}>') }
26
+ it { expect(subject.response_status).to eq(400) }
25
27
  end
26
28
 
27
29
  context 'with string' do
@@ -31,6 +33,7 @@ RSpec.describe Faraday::ClientError do
31
33
  it { expect(subject.response).to be_nil }
32
34
  it { expect(subject.message).to eq('custom message') }
33
35
  it { expect(subject.inspect).to eq('#<Faraday::ClientError #<Faraday::ClientError: custom message>>') }
36
+ it { expect(subject.response_status).to be_nil }
34
37
  end
35
38
 
36
39
  context 'with anything else #to_s' do
@@ -40,6 +43,18 @@ RSpec.describe Faraday::ClientError do
40
43
  it { expect(subject.response).to be_nil }
41
44
  it { expect(subject.message).to eq('["error1", "error2"]') }
42
45
  it { expect(subject.inspect).to eq('#<Faraday::ClientError #<Faraday::ClientError: ["error1", "error2"]>>') }
46
+ it { expect(subject.response_status).to be_nil }
47
+ end
48
+
49
+ context 'with exception string and response hash' do
50
+ let(:exception) { 'custom message' }
51
+ let(:response) { { status: 400 } }
52
+
53
+ it { expect(subject.wrapped_exception).to be_nil }
54
+ it { expect(subject.response).to eq(response) }
55
+ it { expect(subject.message).to eq('custom message') }
56
+ it { expect(subject.inspect).to eq('#<Faraday::ClientError response={:status=>400}>') }
57
+ it { expect(subject.response_status).to eq(400) }
43
58
  end
44
59
  end
45
60
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Faraday::MiddlewareRegistry do
4
+ before do
5
+ stub_const('CustomMiddleware', custom_middleware_klass)
6
+ end
7
+ let(:custom_middleware_klass) { Class.new(Faraday::Middleware) }
8
+ let(:dummy) { Class.new { extend Faraday::MiddlewareRegistry } }
9
+
10
+ after { dummy.unregister_middleware(:custom) }
11
+
12
+ it 'allows to register with constant' do
13
+ dummy.register_middleware(custom: custom_middleware_klass)
14
+ expect(dummy.lookup_middleware(:custom)).to eq(custom_middleware_klass)
15
+ end
16
+
17
+ it 'allows to register with symbol' do
18
+ dummy.register_middleware(custom: :CustomMiddleware)
19
+ expect(dummy.lookup_middleware(:custom)).to eq(custom_middleware_klass)
20
+ end
21
+
22
+ it 'allows to register with string' do
23
+ dummy.register_middleware(custom: 'CustomMiddleware')
24
+ expect(dummy.lookup_middleware(:custom)).to eq(custom_middleware_klass)
25
+ end
26
+
27
+ it 'allows to register with Proc' do
28
+ dummy.register_middleware(custom: -> { custom_middleware_klass })
29
+ expect(dummy.lookup_middleware(:custom)).to eq(custom_middleware_klass)
30
+ end
31
+ end