faraday 1.4.2 → 1.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/examples/client_spec.rb +34 -2
- data/examples/client_test.rb +41 -2
- data/lib/faraday/adapter/test.rb +59 -43
- data/lib/faraday/adapter.rb +1 -4
- data/lib/faraday/autoload.rb +1 -4
- data/lib/faraday/connection.rb +26 -5
- data/lib/faraday/error.rb +0 -6
- data/lib/faraday/request/authorization.rb +14 -7
- data/lib/faraday/request/json.rb +55 -0
- data/lib/faraday/request.rb +7 -8
- data/lib/faraday/response/json.rb +54 -0
- data/lib/faraday/response/logger.rb +2 -4
- data/lib/faraday/response.rb +3 -1
- data/lib/faraday/version.rb +1 -1
- data/lib/faraday.rb +18 -5
- data/spec/faraday/adapter/em_http_spec.rb +39 -37
- data/spec/faraday/adapter/em_synchrony_spec.rb +11 -9
- data/spec/faraday/adapter/test_spec.rb +117 -0
- data/spec/faraday/connection_spec.rb +7 -0
- data/spec/faraday/request/authorization_spec.rb +8 -0
- data/spec/faraday/request/json_spec.rb +111 -0
- data/spec/faraday/response/json_spec.rb +119 -0
- metadata +68 -23
- 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/file_part.rb +0 -128
- data/lib/faraday/param_part.rb +0 -53
- data/lib/faraday/request/multipart.rb +0 -106
- data/lib/faraday/request/retry.rb +0 -239
- data/spec/faraday/request/multipart_spec.rb +0 -302
- data/spec/faraday/request/retry_spec.rb +0 -242
data/lib/faraday/version.rb
CHANGED
data/lib/faraday.rb
CHANGED
@@ -24,14 +24,25 @@ require 'faraday/adapter'
|
|
24
24
|
require 'faraday/request'
|
25
25
|
require 'faraday/response'
|
26
26
|
require 'faraday/error'
|
27
|
-
require 'faraday/
|
28
|
-
|
29
|
-
|
30
|
-
require 'faraday/
|
31
|
-
require 'faraday/
|
27
|
+
require 'faraday/request/url_encoded' # needed by multipart
|
28
|
+
|
29
|
+
# External Middleware gems and their aliases
|
30
|
+
require 'faraday/multipart'
|
31
|
+
require 'faraday/retry'
|
32
|
+
Faraday::Request::Multipart = Faraday::Multipart::Middleware
|
33
|
+
Faraday::Request::Retry = Faraday::Retry::Middleware
|
34
|
+
|
35
|
+
# External Adapters gems
|
36
|
+
unless defined?(JRUBY_VERSION)
|
37
|
+
require 'faraday/em_http'
|
38
|
+
require 'faraday/em_synchrony'
|
39
|
+
end
|
32
40
|
require 'faraday/excon'
|
41
|
+
require 'faraday/httpclient'
|
33
42
|
require 'faraday/net_http'
|
34
43
|
require 'faraday/net_http_persistent'
|
44
|
+
require 'faraday/patron'
|
45
|
+
require 'faraday/rack'
|
35
46
|
|
36
47
|
# This is the main namespace for Faraday.
|
37
48
|
#
|
@@ -46,6 +57,8 @@ require 'faraday/net_http_persistent'
|
|
46
57
|
# conn.get '/'
|
47
58
|
#
|
48
59
|
module Faraday
|
60
|
+
CONTENT_TYPE = 'Content-Type'
|
61
|
+
|
49
62
|
class << self
|
50
63
|
# The root path that Faraday is being loaded from.
|
51
64
|
#
|
@@ -1,47 +1,49 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
unless defined?(JRUBY_VERSION)
|
4
|
+
RSpec.describe Faraday::Adapter::EMHttp do
|
5
|
+
features :request_body_on_query_methods, :reason_phrase_parse, :trace_method,
|
6
|
+
:skip_response_body_on_head, :parallel, :local_socket_binding
|
6
7
|
|
7
|
-
|
8
|
+
it_behaves_like 'an adapter'
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
it 'allows to provide adapter specific configs' do
|
11
|
+
url = URI('https://example.com:1234')
|
12
|
+
adapter = described_class.new nil, inactivity_timeout: 20
|
13
|
+
req = adapter.create_request(url: url, request: {})
|
13
14
|
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
context 'Options' do
|
18
|
-
let(:request) { Faraday::RequestOptions.new }
|
19
|
-
let(:env) { { request: request } }
|
20
|
-
let(:options) { {} }
|
21
|
-
let(:adapter) { Faraday::Adapter::EMHttp.new }
|
22
|
-
|
23
|
-
it 'configures timeout' do
|
24
|
-
request.timeout = 5
|
25
|
-
adapter.configure_timeout(options, env)
|
26
|
-
expect(options[:inactivity_timeout]).to eq(5)
|
27
|
-
expect(options[:connect_timeout]).to eq(5)
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'configures timeout and open_timeout' do
|
31
|
-
request.timeout = 5
|
32
|
-
request.open_timeout = 1
|
33
|
-
adapter.configure_timeout(options, env)
|
34
|
-
expect(options[:inactivity_timeout]).to eq(5)
|
35
|
-
expect(options[:connect_timeout]).to eq(1)
|
15
|
+
expect(req.connopts.inactivity_timeout).to eq(20)
|
36
16
|
end
|
37
17
|
|
38
|
-
|
39
|
-
request.
|
40
|
-
request
|
41
|
-
|
42
|
-
adapter.
|
43
|
-
|
44
|
-
|
18
|
+
context 'Options' do
|
19
|
+
let(:request) { Faraday::RequestOptions.new }
|
20
|
+
let(:env) { { request: request } }
|
21
|
+
let(:options) { {} }
|
22
|
+
let(:adapter) { Faraday::Adapter::EMHttp.new }
|
23
|
+
|
24
|
+
it 'configures timeout' do
|
25
|
+
request.timeout = 5
|
26
|
+
adapter.configure_timeout(options, env)
|
27
|
+
expect(options[:inactivity_timeout]).to eq(5)
|
28
|
+
expect(options[:connect_timeout]).to eq(5)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'configures timeout and open_timeout' do
|
32
|
+
request.timeout = 5
|
33
|
+
request.open_timeout = 1
|
34
|
+
adapter.configure_timeout(options, env)
|
35
|
+
expect(options[:inactivity_timeout]).to eq(5)
|
36
|
+
expect(options[:connect_timeout]).to eq(1)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'configures all timeout settings' do
|
40
|
+
request.timeout = 5
|
41
|
+
request.read_timeout = 3
|
42
|
+
request.open_timeout = 1
|
43
|
+
adapter.configure_timeout(options, env)
|
44
|
+
expect(options[:inactivity_timeout]).to eq(3)
|
45
|
+
expect(options[:connect_timeout]).to eq(1)
|
46
|
+
end
|
45
47
|
end
|
46
48
|
end
|
47
49
|
end
|
@@ -1,16 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
unless defined?(JRUBY_VERSION)
|
4
|
+
RSpec.describe Faraday::Adapter::EMSynchrony do
|
5
|
+
features :request_body_on_query_methods, :reason_phrase_parse,
|
6
|
+
:skip_response_body_on_head, :parallel, :local_socket_binding
|
6
7
|
|
7
|
-
|
8
|
+
it_behaves_like 'an adapter'
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
it 'allows to provide adapter specific configs' do
|
11
|
+
url = URI('https://example.com:1234')
|
12
|
+
adapter = described_class.new nil, inactivity_timeout: 20
|
13
|
+
req = adapter.create_request(url: url, request: {})
|
13
14
|
|
14
|
-
|
15
|
+
expect(req.connopts.inactivity_timeout).to eq(20)
|
16
|
+
end
|
15
17
|
end
|
16
18
|
end
|
@@ -257,4 +257,121 @@ 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
|
+
end
|
260
377
|
end
|
@@ -253,6 +253,13 @@ RSpec.describe Faraday::Connection do
|
|
253
253
|
expect(uri.path).to eq('/sake.html')
|
254
254
|
end
|
255
255
|
|
256
|
+
it 'always returns new URI instance' do
|
257
|
+
conn.url_prefix = 'http://sushi.com'
|
258
|
+
uri1 = conn.build_exclusive_url(nil)
|
259
|
+
uri2 = conn.build_exclusive_url(nil)
|
260
|
+
expect(uri1).not_to equal(uri2)
|
261
|
+
end
|
262
|
+
|
256
263
|
context 'with url_prefixed connection' do
|
257
264
|
let(:url) { 'http://sushi.com/sushi/' }
|
258
265
|
|
@@ -84,5 +84,13 @@ RSpec.describe Faraday::Request::Authorization do
|
|
84
84
|
|
85
85
|
include_examples 'does not interfere with existing authentication'
|
86
86
|
end
|
87
|
+
|
88
|
+
context 'when passed a string and a proc' do
|
89
|
+
let(:auth_config) { ['Bearer', -> { 'custom_from_proc' }] }
|
90
|
+
|
91
|
+
it { expect(response.body).to eq('Bearer custom_from_proc') }
|
92
|
+
|
93
|
+
include_examples 'does not interfere with existing authentication'
|
94
|
+
end
|
87
95
|
end
|
88
96
|
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Faraday::Request::Json do
|
4
|
+
let(:middleware) { described_class.new(->(env) { Faraday::Response.new(env) }) }
|
5
|
+
|
6
|
+
def process(body, content_type = nil)
|
7
|
+
env = { body: body, request_headers: Faraday::Utils::Headers.new }
|
8
|
+
env[:request_headers]['content-type'] = content_type if content_type
|
9
|
+
middleware.call(Faraday::Env.from(env)).env
|
10
|
+
end
|
11
|
+
|
12
|
+
def result_body
|
13
|
+
result[:body]
|
14
|
+
end
|
15
|
+
|
16
|
+
def result_type
|
17
|
+
result[:request_headers]['content-type']
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'no body' do
|
21
|
+
let(:result) { process(nil) }
|
22
|
+
|
23
|
+
it "doesn't change body" do
|
24
|
+
expect(result_body).to be_nil
|
25
|
+
end
|
26
|
+
|
27
|
+
it "doesn't add content type" do
|
28
|
+
expect(result_type).to be_nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'empty body' do
|
33
|
+
let(:result) { process('') }
|
34
|
+
|
35
|
+
it "doesn't change body" do
|
36
|
+
expect(result_body).to be_empty
|
37
|
+
end
|
38
|
+
|
39
|
+
it "doesn't add content type" do
|
40
|
+
expect(result_type).to be_nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'string body' do
|
45
|
+
let(:result) { process('{"a":1}') }
|
46
|
+
|
47
|
+
it "doesn't change body" do
|
48
|
+
expect(result_body).to eq('{"a":1}')
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'adds content type' do
|
52
|
+
expect(result_type).to eq('application/json')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'object body' do
|
57
|
+
let(:result) { process(a: 1) }
|
58
|
+
|
59
|
+
it 'encodes body' do
|
60
|
+
expect(result_body).to eq('{"a":1}')
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'adds content type' do
|
64
|
+
expect(result_type).to eq('application/json')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'empty object body' do
|
69
|
+
let(:result) { process({}) }
|
70
|
+
|
71
|
+
it 'encodes body' do
|
72
|
+
expect(result_body).to eq('{}')
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'object body with json type' do
|
77
|
+
let(:result) { process({ a: 1 }, 'application/json; charset=utf-8') }
|
78
|
+
|
79
|
+
it 'encodes body' do
|
80
|
+
expect(result_body).to eq('{"a":1}')
|
81
|
+
end
|
82
|
+
|
83
|
+
it "doesn't change content type" do
|
84
|
+
expect(result_type).to eq('application/json; charset=utf-8')
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'object body with vendor json type' do
|
89
|
+
let(:result) { process({ a: 1 }, 'application/vnd.myapp.v1+json; charset=utf-8') }
|
90
|
+
|
91
|
+
it 'encodes body' do
|
92
|
+
expect(result_body).to eq('{"a":1}')
|
93
|
+
end
|
94
|
+
|
95
|
+
it "doesn't change content type" do
|
96
|
+
expect(result_type).to eq('application/vnd.myapp.v1+json; charset=utf-8')
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'object body with incompatible type' do
|
101
|
+
let(:result) { process({ a: 1 }, 'application/xml; charset=utf-8') }
|
102
|
+
|
103
|
+
it "doesn't change body" do
|
104
|
+
expect(result_body).to eq(a: 1)
|
105
|
+
end
|
106
|
+
|
107
|
+
it "doesn't change content type" do
|
108
|
+
expect(result_type).to eq('application/xml; charset=utf-8')
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Faraday::Response::Json, type: :response do
|
4
|
+
let(:options) { {} }
|
5
|
+
let(:headers) { {} }
|
6
|
+
let(:middleware) do
|
7
|
+
described_class.new(lambda { |env|
|
8
|
+
Faraday::Response.new(env)
|
9
|
+
}, **options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def process(body, content_type = 'application/json', options = {})
|
13
|
+
env = {
|
14
|
+
body: body, request: options,
|
15
|
+
request_headers: Faraday::Utils::Headers.new,
|
16
|
+
response_headers: Faraday::Utils::Headers.new(headers)
|
17
|
+
}
|
18
|
+
env[:response_headers]['content-type'] = content_type if content_type
|
19
|
+
yield(env) if block_given?
|
20
|
+
middleware.call(Faraday::Env.from(env))
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'no type matching' do
|
24
|
+
it "doesn't change nil body" do
|
25
|
+
expect(process(nil).body).to be_nil
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'nullifies empty body' do
|
29
|
+
expect(process('').body).to be_nil
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'parses json body' do
|
33
|
+
response = process('{"a":1}')
|
34
|
+
expect(response.body).to eq('a' => 1)
|
35
|
+
expect(response.env[:raw_body]).to be_nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'with preserving raw' do
|
40
|
+
let(:options) { { preserve_raw: true } }
|
41
|
+
|
42
|
+
it 'parses json body' do
|
43
|
+
response = process('{"a":1}')
|
44
|
+
expect(response.body).to eq('a' => 1)
|
45
|
+
expect(response.env[:raw_body]).to eq('{"a":1}')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'with default regexp type matching' do
|
50
|
+
it 'parses json body of correct type' do
|
51
|
+
response = process('{"a":1}', 'application/x-json')
|
52
|
+
expect(response.body).to eq('a' => 1)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'ignores json body of incorrect type' do
|
56
|
+
response = process('{"a":1}', 'text/json-xml')
|
57
|
+
expect(response.body).to eq('{"a":1}')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'with array type matching' do
|
62
|
+
let(:options) { { content_type: %w[a/b c/d] } }
|
63
|
+
|
64
|
+
it 'parses json body of correct type' do
|
65
|
+
expect(process('{"a":1}', 'a/b').body).to be_a(Hash)
|
66
|
+
expect(process('{"a":1}', 'c/d').body).to be_a(Hash)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'ignores json body of incorrect type' do
|
70
|
+
expect(process('{"a":1}', 'a/d').body).not_to be_a(Hash)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'chokes on invalid json' do
|
75
|
+
expect { process('{!') }.to raise_error(Faraday::ParsingError)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'includes the response on the ParsingError instance' do
|
79
|
+
begin
|
80
|
+
process('{') { |env| env[:response] = Faraday::Response.new }
|
81
|
+
raise 'Parsing should have failed.'
|
82
|
+
rescue Faraday::ParsingError => e
|
83
|
+
expect(e.response).to be_a(Faraday::Response)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'HEAD responses' do
|
88
|
+
it "nullifies the body if it's only one space" do
|
89
|
+
response = process(' ')
|
90
|
+
expect(response.body).to be_nil
|
91
|
+
end
|
92
|
+
|
93
|
+
it "nullifies the body if it's two spaces" do
|
94
|
+
response = process(' ')
|
95
|
+
expect(response.body).to be_nil
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'JSON options' do
|
100
|
+
let(:body) { '{"a": 1}' }
|
101
|
+
let(:result) { { a: 1 } }
|
102
|
+
let(:options) do
|
103
|
+
{
|
104
|
+
parser_options: {
|
105
|
+
symbolize_names: true
|
106
|
+
}
|
107
|
+
}
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'passes relevant options to JSON parse' do
|
111
|
+
expect(::JSON).to receive(:parse)
|
112
|
+
.with(body, options[:parser_options])
|
113
|
+
.and_return(result)
|
114
|
+
|
115
|
+
response = process(body)
|
116
|
+
expect(response.body).to eq(result)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|