faraday 1.4.1 → 2.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +197 -3
- data/LICENSE.md +1 -1
- data/README.md +34 -20
- data/Rakefile +3 -1
- data/examples/client_spec.rb +67 -13
- data/examples/client_test.rb +80 -15
- data/lib/faraday/adapter/test.rb +117 -52
- data/lib/faraday/adapter.rb +5 -14
- data/lib/faraday/connection.rb +70 -130
- data/lib/faraday/encoders/nested_params_encoder.rb +14 -7
- data/lib/faraday/error.rb +20 -11
- data/lib/faraday/logging/formatter.rb +28 -15
- data/lib/faraday/middleware.rb +3 -1
- data/lib/faraday/middleware_registry.rb +17 -63
- data/lib/faraday/options/connection_options.rb +7 -6
- data/lib/faraday/options/env.rb +85 -62
- data/lib/faraday/options/proxy_options.rb +11 -3
- data/lib/faraday/options/request_options.rb +7 -6
- data/lib/faraday/options/ssl_options.rb +56 -45
- data/lib/faraday/options.rb +7 -6
- data/lib/faraday/rack_builder.rb +23 -21
- data/lib/faraday/request/authorization.rb +37 -38
- data/lib/faraday/request/instrumentation.rb +5 -1
- data/lib/faraday/request/json.rb +70 -0
- data/lib/faraday/request/url_encoded.rb +5 -1
- data/lib/faraday/request.rb +20 -37
- data/lib/faraday/response/json.rb +73 -0
- data/lib/faraday/response/logger.rb +8 -4
- data/lib/faraday/response/raise_error.rb +33 -6
- data/lib/faraday/response.rb +10 -20
- data/lib/faraday/utils/headers.rb +7 -2
- data/lib/faraday/utils.rb +11 -7
- data/lib/faraday/version.rb +1 -1
- data/lib/faraday.rb +10 -31
- data/spec/faraday/adapter/test_spec.rb +182 -0
- data/spec/faraday/connection_spec.rb +177 -90
- data/spec/faraday/error_spec.rb +31 -6
- data/spec/faraday/middleware_registry_spec.rb +31 -0
- data/spec/faraday/middleware_spec.rb +18 -0
- data/spec/faraday/options/env_spec.rb +8 -2
- data/spec/faraday/options/options_spec.rb +1 -1
- data/spec/faraday/options/proxy_options_spec.rb +15 -0
- data/spec/faraday/params_encoders/nested_spec.rb +8 -0
- data/spec/faraday/rack_builder_spec.rb +26 -54
- data/spec/faraday/request/authorization_spec.rb +54 -24
- data/spec/faraday/request/instrumentation_spec.rb +5 -7
- data/spec/faraday/request/json_spec.rb +199 -0
- data/spec/faraday/request/url_encoded_spec.rb +12 -2
- data/spec/faraday/request_spec.rb +5 -15
- data/spec/faraday/response/json_spec.rb +189 -0
- data/spec/faraday/response/logger_spec.rb +38 -0
- data/spec/faraday/response/raise_error_spec.rb +47 -5
- data/spec/faraday/response_spec.rb +3 -1
- data/spec/faraday/utils/headers_spec.rb +22 -4
- data/spec/faraday/utils_spec.rb +63 -1
- data/spec/faraday_spec.rb +8 -4
- data/spec/spec_helper.rb +6 -5
- data/spec/support/fake_safe_buffer.rb +1 -1
- data/spec/support/helper_methods.rb +0 -37
- data/spec/support/shared_examples/adapter.rb +2 -2
- data/spec/support/shared_examples/request_method.rb +22 -21
- metadata +14 -94
- data/lib/faraday/adapter/em_http.rb +0 -289
- data/lib/faraday/adapter/em_http_ssl_patch.rb +0 -62
- data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +0 -69
- data/lib/faraday/adapter/em_synchrony.rb +0 -153
- data/lib/faraday/adapter/httpclient.rb +0 -152
- data/lib/faraday/adapter/patron.rb +0 -132
- data/lib/faraday/adapter/rack.rb +0 -75
- data/lib/faraday/adapter/typhoeus.rb +0 -15
- data/lib/faraday/autoload.rb +0 -92
- data/lib/faraday/dependency_loader.rb +0 -37
- data/lib/faraday/file_part.rb +0 -128
- data/lib/faraday/param_part.rb +0 -53
- data/lib/faraday/request/basic_authentication.rb +0 -20
- data/lib/faraday/request/multipart.rb +0 -106
- data/lib/faraday/request/retry.rb +0 -239
- data/lib/faraday/request/token_authentication.rb +0 -20
- data/spec/faraday/adapter/em_http_spec.rb +0 -47
- data/spec/faraday/adapter/em_synchrony_spec.rb +0 -16
- data/spec/faraday/adapter/excon_spec.rb +0 -49
- data/spec/faraday/adapter/httpclient_spec.rb +0 -73
- data/spec/faraday/adapter/net_http_spec.rb +0 -64
- data/spec/faraday/adapter/patron_spec.rb +0 -18
- data/spec/faraday/adapter/rack_spec.rb +0 -8
- data/spec/faraday/adapter/typhoeus_spec.rb +0 -7
- data/spec/faraday/composite_read_io_spec.rb +0 -80
- data/spec/faraday/request/multipart_spec.rb +0 -302
- data/spec/faraday/request/retry_spec.rb +0 -242
- data/spec/faraday/response/middleware_spec.rb +0 -68
- data/spec/support/webmock_rack_app.rb +0 -68
data/lib/faraday.rb
CHANGED
@@ -4,16 +4,10 @@ require 'cgi'
|
|
4
4
|
require 'date'
|
5
5
|
require 'set'
|
6
6
|
require 'forwardable'
|
7
|
-
require 'faraday/middleware_registry'
|
8
|
-
require 'faraday/dependency_loader'
|
9
|
-
|
10
|
-
unless defined?(::Faraday::Timer)
|
11
|
-
require 'timeout'
|
12
|
-
::Faraday::Timer = Timeout
|
13
|
-
end
|
14
|
-
|
15
7
|
require 'faraday/version'
|
16
8
|
require 'faraday/methods'
|
9
|
+
require 'faraday/error'
|
10
|
+
require 'faraday/middleware_registry'
|
17
11
|
require 'faraday/utils'
|
18
12
|
require 'faraday/options'
|
19
13
|
require 'faraday/connection'
|
@@ -23,14 +17,7 @@ require 'faraday/middleware'
|
|
23
17
|
require 'faraday/adapter'
|
24
18
|
require 'faraday/request'
|
25
19
|
require 'faraday/response'
|
26
|
-
require 'faraday/error'
|
27
|
-
require 'faraday/file_part'
|
28
|
-
require 'faraday/param_part'
|
29
|
-
|
30
20
|
require 'faraday/net_http'
|
31
|
-
require 'faraday/net_http_persistent'
|
32
|
-
require 'faraday/excon'
|
33
|
-
|
34
21
|
# This is the main namespace for Faraday.
|
35
22
|
#
|
36
23
|
# It provides methods to create {Connection} objects, and HTTP-related
|
@@ -44,6 +31,8 @@ require 'faraday/excon'
|
|
44
31
|
# conn.get '/'
|
45
32
|
#
|
46
33
|
module Faraday
|
34
|
+
CONTENT_TYPE = 'Content-Type'
|
35
|
+
|
47
36
|
class << self
|
48
37
|
# The root path that Faraday is being loaded from.
|
49
38
|
#
|
@@ -65,6 +54,10 @@ module Faraday
|
|
65
54
|
# @return [Symbol] the new default_adapter.
|
66
55
|
attr_reader :default_adapter
|
67
56
|
|
57
|
+
# Option for the default_adapter
|
58
|
+
# @return [Hash] default_adapter options
|
59
|
+
attr_accessor :default_adapter_options
|
60
|
+
|
68
61
|
# Documented below, see default_connection
|
69
62
|
attr_writer :default_connection
|
70
63
|
|
@@ -101,23 +94,10 @@ module Faraday
|
|
101
94
|
# params: { page: 1 }
|
102
95
|
# # => Faraday::Connection to http://faraday.com?page=1
|
103
96
|
def new(url = nil, options = {}, &block)
|
104
|
-
options =
|
97
|
+
options = Utils.deep_merge(default_connection_options, options)
|
105
98
|
Faraday::Connection.new(url, options, &block)
|
106
99
|
end
|
107
100
|
|
108
|
-
# @private
|
109
|
-
# Internal: Requires internal Faraday libraries.
|
110
|
-
#
|
111
|
-
# @param libs [Array] one or more relative String names to Faraday classes.
|
112
|
-
# @return [void]
|
113
|
-
def require_libs(*libs)
|
114
|
-
libs.each do |lib|
|
115
|
-
require "#{lib_path}/#{lib}"
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
alias require_lib require_libs
|
120
|
-
|
121
101
|
# Documented elsewhere, see default_adapter reader
|
122
102
|
def default_adapter=(adapter)
|
123
103
|
@default_connection = nil
|
@@ -173,6 +153,5 @@ module Faraday
|
|
173
153
|
self.root_path = File.expand_path __dir__
|
174
154
|
self.lib_path = File.expand_path 'faraday', __dir__
|
175
155
|
self.default_adapter = :net_http
|
176
|
-
|
177
|
-
require_lib 'autoload' unless ENV['FARADAY_NO_AUTOLOAD']
|
156
|
+
self.default_adapter_options = {}
|
178
157
|
end
|
@@ -257,4 +257,186 @@ RSpec.describe Faraday::Adapter::Test do
|
|
257
257
|
it { expect { request }.to raise_error described_class::Stubs::NotFound }
|
258
258
|
end
|
259
259
|
end
|
260
|
+
|
261
|
+
describe 'for request with non default params encoder' do
|
262
|
+
let(:connection) do
|
263
|
+
Faraday.new(request: { params_encoder: Faraday::FlatParamsEncoder }) do |builder|
|
264
|
+
builder.adapter :test, stubs
|
265
|
+
end
|
266
|
+
end
|
267
|
+
let(:stubs) do
|
268
|
+
described_class::Stubs.new do |stubs|
|
269
|
+
stubs.get('/path?a=x&a=y&a=z') { [200, {}, 'a'] }
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
context 'when all flat param values are correctly set' do
|
274
|
+
subject(:request) { connection.get('/path?a=x&a=y&a=z') }
|
275
|
+
|
276
|
+
it { expect(request.status).to eq 200 }
|
277
|
+
end
|
278
|
+
|
279
|
+
shared_examples 'raise NotFound when params do not satisfy the flat param values' do |params|
|
280
|
+
subject(:request) { connection.get('/path', params) }
|
281
|
+
|
282
|
+
context "with #{params.inspect}" do
|
283
|
+
it { expect { request }.to raise_error described_class::Stubs::NotFound }
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
it_behaves_like 'raise NotFound when params do not satisfy the flat param values', { a: %w[x] }
|
288
|
+
it_behaves_like 'raise NotFound when params do not satisfy the flat param values', { a: %w[x y] }
|
289
|
+
it_behaves_like 'raise NotFound when params do not satisfy the flat param values', { a: %w[x z y] } # NOTE: The order of the value is also compared.
|
290
|
+
it_behaves_like 'raise NotFound when params do not satisfy the flat param values', { b: %w[x y z] }
|
291
|
+
end
|
292
|
+
|
293
|
+
describe 'strict_mode' do
|
294
|
+
let(:stubs) do
|
295
|
+
described_class::Stubs.new(strict_mode: true) do |stubs|
|
296
|
+
stubs.get('/strict?a=12&b=xy', 'Authorization' => 'Bearer m_ck', 'X-C' => 'hello') { [200, {}, 'a'] }
|
297
|
+
stubs.get('/with_user_agent?a=12&b=xy', authorization: 'Bearer m_ck', 'User-Agent' => 'My Agent') { [200, {}, 'a'] }
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
context 'when params and headers are exactly set' do
|
302
|
+
subject(:request) { connection.get('/strict', { a: '12', b: 'xy' }, { authorization: 'Bearer m_ck', x_c: 'hello' }) }
|
303
|
+
|
304
|
+
it { expect(request.status).to eq 200 }
|
305
|
+
end
|
306
|
+
|
307
|
+
context 'when params and headers are exactly set with a custom user agent' do
|
308
|
+
subject(:request) { connection.get('/with_user_agent', { a: '12', b: 'xy' }, { authorization: 'Bearer m_ck', 'User-Agent' => 'My Agent' }) }
|
309
|
+
|
310
|
+
it { expect(request.status).to eq 200 }
|
311
|
+
end
|
312
|
+
|
313
|
+
shared_examples 'raise NotFound when params do not satisfy the strict check' do |params|
|
314
|
+
subject(:request) { connection.get('/strict', params, { 'Authorization' => 'Bearer m_ck', 'X-C' => 'hello' }) }
|
315
|
+
|
316
|
+
context "with #{params.inspect}" do
|
317
|
+
it { expect { request }.to raise_error described_class::Stubs::NotFound }
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
it_behaves_like 'raise NotFound when params do not satisfy the strict check', { a: '12' }
|
322
|
+
it_behaves_like 'raise NotFound when params do not satisfy the strict check', { b: 'xy' }
|
323
|
+
it_behaves_like 'raise NotFound when params do not satisfy the strict check', { a: '123', b: 'xy' }
|
324
|
+
it_behaves_like 'raise NotFound when params do not satisfy the strict check', { a: '12', b: 'xyz' }
|
325
|
+
it_behaves_like 'raise NotFound when params do not satisfy the strict check', { a: '12', b: 'xy', c: 'hello' }
|
326
|
+
it_behaves_like 'raise NotFound when params do not satisfy the strict check', { additional: 'special', a: '12', b: 'xy', c: 'hello' }
|
327
|
+
|
328
|
+
shared_examples 'raise NotFound when headers do not satisfy the strict check' do |path, headers|
|
329
|
+
subject(:request) { connection.get(path, { a: 12, b: 'xy' }, headers) }
|
330
|
+
|
331
|
+
context "with #{headers.inspect}" do
|
332
|
+
it { expect { request }.to raise_error described_class::Stubs::NotFound }
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
it_behaves_like 'raise NotFound when headers do not satisfy the strict check', '/strict', { authorization: 'Bearer m_ck' }
|
337
|
+
it_behaves_like 'raise NotFound when headers do not satisfy the strict check', '/strict', { 'X-C' => 'hello' }
|
338
|
+
it_behaves_like 'raise NotFound when headers do not satisfy the strict check', '/strict', { authorization: 'Bearer m_ck', 'x-c': 'Hi' }
|
339
|
+
it_behaves_like 'raise NotFound when headers do not satisfy the strict check', '/strict', { authorization: 'Basic m_ck', 'x-c': 'hello' }
|
340
|
+
it_behaves_like 'raise NotFound when headers do not satisfy the strict check', '/strict', { authorization: 'Bearer m_ck', 'x-c': 'hello', x_special: 'special' }
|
341
|
+
it_behaves_like 'raise NotFound when headers do not satisfy the strict check', '/with_user_agent', { authorization: 'Bearer m_ck' }
|
342
|
+
it_behaves_like 'raise NotFound when headers do not satisfy the strict check', '/with_user_agent', { authorization: 'Bearer m_ck', user_agent: 'Unknown' }
|
343
|
+
it_behaves_like 'raise NotFound when headers do not satisfy the strict check', '/with_user_agent', { authorization: 'Bearer m_ck', user_agent: 'My Agent', x_special: 'special' }
|
344
|
+
|
345
|
+
context 'when strict_mode is disabled' do
|
346
|
+
before do
|
347
|
+
stubs.strict_mode = false
|
348
|
+
end
|
349
|
+
|
350
|
+
shared_examples 'does not raise NotFound even when params do not satisfy the strict check' do |params|
|
351
|
+
subject(:request) { connection.get('/strict', params, { 'Authorization' => 'Bearer m_ck', 'X-C' => 'hello' }) }
|
352
|
+
|
353
|
+
context "with #{params.inspect}" do
|
354
|
+
it { expect(request.status).to eq 200 }
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
it_behaves_like 'does not raise NotFound even when params do not satisfy the strict check', { a: '12', b: 'xy' }
|
359
|
+
it_behaves_like 'does not raise NotFound even when params do not satisfy the strict check', { a: '12', b: 'xy', c: 'hello' }
|
360
|
+
it_behaves_like 'does not raise NotFound even when params do not satisfy the strict check', { additional: 'special', a: '12', b: 'xy', c: 'hello' }
|
361
|
+
|
362
|
+
shared_examples 'does not raise NotFound even when headers do not satisfy the strict check' do |path, headers|
|
363
|
+
subject(:request) { connection.get(path, { a: 12, b: 'xy' }, headers) }
|
364
|
+
|
365
|
+
context "with #{headers.inspect}" do
|
366
|
+
it { expect(request.status).to eq 200 }
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
it_behaves_like 'does not raise NotFound even when headers do not satisfy the strict check', '/strict', { authorization: 'Bearer m_ck', 'x-c': 'hello' }
|
371
|
+
it_behaves_like 'does not raise NotFound even when headers do not satisfy the strict check', '/strict', { authorization: 'Bearer m_ck', 'x-c': 'hello', x_special: 'special' }
|
372
|
+
it_behaves_like 'does not raise NotFound even when headers do not satisfy the strict check', '/strict', { authorization: 'Bearer m_ck', 'x-c': 'hello', user_agent: 'Special Agent' }
|
373
|
+
it_behaves_like 'does not raise NotFound even when headers do not satisfy the strict check', '/with_user_agent', { authorization: 'Bearer m_ck', user_agent: 'My Agent' }
|
374
|
+
it_behaves_like 'does not raise NotFound even when headers do not satisfy the strict check', '/with_user_agent', { authorization: 'Bearer m_ck', user_agent: 'My Agent', x_special: 'special' }
|
375
|
+
end
|
376
|
+
|
377
|
+
describe 'body_match?' do
|
378
|
+
let(:stubs) do
|
379
|
+
described_class::Stubs.new do |stubs|
|
380
|
+
stubs.post('/no_check') { [200, {}, 'ok'] }
|
381
|
+
stubs.post('/with_string', 'abc') { [200, {}, 'ok'] }
|
382
|
+
stubs.post(
|
383
|
+
'/with_proc',
|
384
|
+
->(request_body) { JSON.parse(request_body, symbolize_names: true) == { x: '!', a: [{ m: [{ a: true }], n: 123 }] } },
|
385
|
+
{ content_type: 'application/json' }
|
386
|
+
) do
|
387
|
+
[200, {}, 'ok']
|
388
|
+
end
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
context 'when trying without any args for body' do
|
393
|
+
subject(:without_body) { connection.post('/no_check') }
|
394
|
+
|
395
|
+
it { expect(without_body.status).to eq 200 }
|
396
|
+
end
|
397
|
+
|
398
|
+
context 'when trying with string body stubs' do
|
399
|
+
subject(:with_string) { connection.post('/with_string', 'abc') }
|
400
|
+
|
401
|
+
it { expect(with_string.status).to eq 200 }
|
402
|
+
end
|
403
|
+
|
404
|
+
context 'when trying with proc body stubs' do
|
405
|
+
subject(:with_proc) do
|
406
|
+
connection.post('/with_proc', JSON.dump(a: [{ n: 123, m: [{ a: true }] }], x: '!'), { 'Content-Type' => 'application/json' })
|
407
|
+
end
|
408
|
+
|
409
|
+
it { expect(with_proc.status).to eq 200 }
|
410
|
+
end
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
414
|
+
describe 'request timeout' do
|
415
|
+
subject(:request) do
|
416
|
+
connection.get('/sleep') do |req|
|
417
|
+
req.options.timeout = timeout
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
before do
|
422
|
+
stubs.get('/sleep') do
|
423
|
+
sleep(0.01)
|
424
|
+
[200, {}, '']
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
context 'when request is within timeout' do
|
429
|
+
let(:timeout) { 1 }
|
430
|
+
|
431
|
+
it { expect(request.status).to eq 200 }
|
432
|
+
end
|
433
|
+
|
434
|
+
context 'when request is too slow' do
|
435
|
+
let(:timeout) { 0.001 }
|
436
|
+
|
437
|
+
it 'raises an exception' do
|
438
|
+
expect { request }.to raise_error(Faraday::TimeoutError)
|
439
|
+
end
|
440
|
+
end
|
441
|
+
end
|
260
442
|
end
|