faraday 0.17.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +69 -9
- data/LICENSE.md +1 -1
- data/README.md +17 -347
- data/Rakefile +1 -7
- data/examples/client_spec.rb +65 -0
- data/examples/client_test.rb +79 -0
- data/lib/faraday.rb +94 -176
- data/lib/faraday/adapter.rb +83 -22
- data/lib/faraday/adapter/em_http.rb +143 -100
- data/lib/faraday/adapter/em_http_ssl_patch.rb +24 -18
- data/lib/faraday/adapter/em_synchrony.rb +104 -60
- data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +18 -15
- data/lib/faraday/adapter/excon.rb +98 -56
- data/lib/faraday/adapter/httpclient.rb +83 -59
- data/lib/faraday/adapter/net_http.rb +130 -63
- data/lib/faraday/adapter/net_http_persistent.rb +51 -28
- data/lib/faraday/adapter/patron.rb +80 -43
- data/lib/faraday/adapter/rack.rb +30 -13
- data/lib/faraday/adapter/test.rb +86 -53
- data/lib/faraday/adapter/typhoeus.rb +4 -1
- data/lib/faraday/adapter_registry.rb +30 -0
- data/lib/faraday/autoload.rb +47 -36
- data/lib/faraday/connection.rb +312 -182
- data/lib/faraday/dependency_loader.rb +39 -0
- data/lib/faraday/encoders/flat_params_encoder.rb +105 -0
- data/lib/faraday/encoders/nested_params_encoder.rb +176 -0
- data/lib/faraday/error.rb +46 -25
- data/lib/faraday/file_part.rb +128 -0
- data/lib/faraday/logging/formatter.rb +105 -0
- data/lib/faraday/middleware.rb +12 -28
- data/lib/faraday/middleware_registry.rb +129 -0
- data/lib/faraday/options.rb +38 -193
- data/lib/faraday/options/connection_options.rb +22 -0
- data/lib/faraday/options/env.rb +181 -0
- data/lib/faraday/options/proxy_options.rb +28 -0
- data/lib/faraday/options/request_options.rb +22 -0
- data/lib/faraday/options/ssl_options.rb +59 -0
- data/lib/faraday/param_part.rb +53 -0
- data/lib/faraday/parameters.rb +4 -197
- data/lib/faraday/rack_builder.rb +77 -65
- data/lib/faraday/request.rb +86 -44
- data/lib/faraday/request/authorization.rb +44 -30
- data/lib/faraday/request/basic_authentication.rb +14 -7
- data/lib/faraday/request/instrumentation.rb +45 -27
- data/lib/faraday/request/multipart.rb +86 -48
- data/lib/faraday/request/retry.rb +197 -171
- data/lib/faraday/request/token_authentication.rb +15 -10
- data/lib/faraday/request/url_encoded.rb +43 -23
- data/lib/faraday/response.rb +24 -14
- data/lib/faraday/response/logger.rb +22 -69
- data/lib/faraday/response/raise_error.rb +49 -18
- data/lib/faraday/utils.rb +38 -247
- data/lib/faraday/utils/headers.rb +139 -0
- data/lib/faraday/utils/params_hash.rb +61 -0
- data/spec/external_adapters/faraday_specs_setup.rb +14 -0
- data/spec/faraday/adapter/em_http_spec.rb +47 -0
- data/spec/faraday/adapter/em_synchrony_spec.rb +16 -0
- data/spec/faraday/adapter/excon_spec.rb +49 -0
- data/spec/faraday/adapter/httpclient_spec.rb +73 -0
- data/spec/faraday/adapter/net_http_persistent_spec.rb +57 -0
- data/spec/faraday/adapter/net_http_spec.rb +64 -0
- data/spec/faraday/adapter/patron_spec.rb +18 -0
- data/spec/faraday/adapter/rack_spec.rb +8 -0
- data/spec/faraday/adapter/test_spec.rb +260 -0
- data/spec/faraday/adapter/typhoeus_spec.rb +7 -0
- data/spec/faraday/adapter_registry_spec.rb +28 -0
- data/spec/faraday/adapter_spec.rb +55 -0
- data/spec/faraday/composite_read_io_spec.rb +80 -0
- data/spec/faraday/connection_spec.rb +691 -0
- data/spec/faraday/error_spec.rb +0 -57
- data/spec/faraday/middleware_spec.rb +26 -0
- data/spec/faraday/options/env_spec.rb +70 -0
- data/spec/faraday/options/options_spec.rb +297 -0
- data/spec/faraday/options/proxy_options_spec.rb +37 -0
- data/spec/faraday/options/request_options_spec.rb +19 -0
- data/spec/faraday/params_encoders/flat_spec.rb +42 -0
- data/spec/faraday/params_encoders/nested_spec.rb +142 -0
- data/spec/faraday/rack_builder_spec.rb +345 -0
- data/spec/faraday/request/authorization_spec.rb +88 -0
- data/spec/faraday/request/instrumentation_spec.rb +76 -0
- data/spec/faraday/request/multipart_spec.rb +302 -0
- data/spec/faraday/request/retry_spec.rb +242 -0
- data/spec/faraday/request/url_encoded_spec.rb +83 -0
- data/spec/faraday/request_spec.rb +120 -0
- data/spec/faraday/response/logger_spec.rb +220 -0
- data/spec/faraday/response/middleware_spec.rb +68 -0
- data/spec/faraday/response/raise_error_spec.rb +60 -16
- data/spec/faraday/response_spec.rb +75 -0
- data/spec/faraday/utils/headers_spec.rb +82 -0
- data/spec/faraday/utils_spec.rb +56 -0
- data/spec/faraday_spec.rb +37 -0
- data/spec/spec_helper.rb +63 -35
- data/spec/support/disabling_stub.rb +14 -0
- data/spec/support/fake_safe_buffer.rb +15 -0
- data/spec/support/helper_methods.rb +133 -0
- data/spec/support/shared_examples/adapter.rb +104 -0
- data/spec/support/shared_examples/params_encoder.rb +18 -0
- data/spec/support/shared_examples/request_method.rb +234 -0
- data/spec/support/streaming_response_checker.rb +35 -0
- data/spec/support/webmock_rack_app.rb +68 -0
- metadata +80 -37
- data/lib/faraday/deprecate.rb +0 -101
- data/lib/faraday/upload_io.rb +0 -67
- data/spec/faraday/deprecate_spec.rb +0 -69
- data/test/adapters/default_test.rb +0 -14
- data/test/adapters/em_http_test.rb +0 -30
- data/test/adapters/em_synchrony_test.rb +0 -32
- data/test/adapters/excon_test.rb +0 -30
- data/test/adapters/httpclient_test.rb +0 -34
- data/test/adapters/integration.rb +0 -263
- data/test/adapters/logger_test.rb +0 -136
- data/test/adapters/net_http_persistent_test.rb +0 -114
- data/test/adapters/net_http_test.rb +0 -79
- data/test/adapters/patron_test.rb +0 -40
- data/test/adapters/rack_test.rb +0 -38
- data/test/adapters/test_middleware_test.rb +0 -157
- data/test/adapters/typhoeus_test.rb +0 -38
- data/test/authentication_middleware_test.rb +0 -65
- data/test/composite_read_io_test.rb +0 -109
- data/test/connection_test.rb +0 -738
- data/test/env_test.rb +0 -268
- data/test/helper.rb +0 -75
- data/test/live_server.rb +0 -67
- data/test/middleware/instrumentation_test.rb +0 -88
- data/test/middleware/retry_test.rb +0 -282
- data/test/middleware_stack_test.rb +0 -260
- data/test/multibyte.txt +0 -1
- data/test/options_test.rb +0 -333
- data/test/parameters_test.rb +0 -157
- data/test/request_middleware_test.rb +0 -126
- data/test/response_middleware_test.rb +0 -72
- data/test/strawberry.rb +0 -2
- data/test/utils_test.rb +0 -98
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Faraday::Response::Middleware do
|
4
|
+
let(:conn) do
|
5
|
+
Faraday.new do |b|
|
6
|
+
b.use custom_middleware
|
7
|
+
b.adapter :test do |stub|
|
8
|
+
stub.get('ok') { [200, { 'Content-Type' => 'text/html' }, '<body></body>'] }
|
9
|
+
stub.get('not_modified') { [304, nil, nil] }
|
10
|
+
stub.get('no_content') { [204, nil, nil] }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'with a custom ResponseMiddleware' do
|
16
|
+
let(:custom_middleware) do
|
17
|
+
Class.new(Faraday::Response::Middleware) do
|
18
|
+
def parse(body)
|
19
|
+
body.upcase
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'parses the response' do
|
25
|
+
expect(conn.get('ok').body).to eq('<BODY></BODY>')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'with a custom ResponseMiddleware and private parse' do
|
30
|
+
let(:custom_middleware) do
|
31
|
+
Class.new(Faraday::Response::Middleware) do
|
32
|
+
private
|
33
|
+
|
34
|
+
def parse(body)
|
35
|
+
body.upcase
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'parses the response' do
|
41
|
+
expect(conn.get('ok').body).to eq('<BODY></BODY>')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'with a custom ResponseMiddleware but empty response' do
|
46
|
+
let(:custom_middleware) do
|
47
|
+
Class.new(Faraday::Response::Middleware) do
|
48
|
+
def parse(_body)
|
49
|
+
raise 'this should not be called'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'raises exception for 200 responses' do
|
55
|
+
expect { conn.get('ok') }.to raise_error(StandardError)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'doesn\'t call the middleware for 204 responses' do
|
59
|
+
expect_any_instance_of(custom_middleware).not_to receive(:parse)
|
60
|
+
expect(conn.get('no_content').body).to be_nil
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'doesn\'t call the middleware for 304 responses' do
|
64
|
+
expect_any_instance_of(custom_middleware).not_to receive(:parse)
|
65
|
+
expect(conn.get('not_modified').body).to be_nil
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -14,7 +14,7 @@ RSpec.describe Faraday::Response::RaiseError do
|
|
14
14
|
stub.get('conflict') { [409, { 'X-Reason' => 'because' }, 'keep looking'] }
|
15
15
|
stub.get('unprocessable-entity') { [422, { 'X-Reason' => 'because' }, 'keep looking'] }
|
16
16
|
stub.get('4xx') { [499, { 'X-Reason' => 'because' }, 'keep looking'] }
|
17
|
-
stub.get('nil-status') { [nil, { 'X-Reason' => '
|
17
|
+
stub.get('nil-status') { [nil, { 'X-Reason' => 'nil' }, 'fail'] }
|
18
18
|
stub.get('server-error') { [500, { 'X-Error' => 'bailout' }, 'fail'] }
|
19
19
|
end
|
20
20
|
end
|
@@ -24,24 +24,27 @@ RSpec.describe Faraday::Response::RaiseError do
|
|
24
24
|
expect { conn.get('ok') }.not_to raise_error
|
25
25
|
end
|
26
26
|
|
27
|
-
it 'raises Faraday::
|
28
|
-
expect { conn.get('bad-request') }.to raise_error(Faraday::
|
27
|
+
it 'raises Faraday::BadRequestError for 400 responses' do
|
28
|
+
expect { conn.get('bad-request') }.to raise_error(Faraday::BadRequestError) do |ex|
|
29
29
|
expect(ex.message).to eq('the server responded with status 400')
|
30
30
|
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
31
|
+
expect(ex.response[:status]).to eq(400)
|
31
32
|
end
|
32
33
|
end
|
33
34
|
|
34
|
-
it 'raises Faraday::
|
35
|
-
expect { conn.get('unauthorized') }.to raise_error(Faraday::
|
35
|
+
it 'raises Faraday::UnauthorizedError for 401 responses' do
|
36
|
+
expect { conn.get('unauthorized') }.to raise_error(Faraday::UnauthorizedError) do |ex|
|
36
37
|
expect(ex.message).to eq('the server responded with status 401')
|
37
38
|
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
39
|
+
expect(ex.response[:status]).to eq(401)
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
41
|
-
it 'raises Faraday::
|
42
|
-
expect { conn.get('forbidden') }.to raise_error(Faraday::
|
43
|
+
it 'raises Faraday::ForbiddenError for 403 responses' do
|
44
|
+
expect { conn.get('forbidden') }.to raise_error(Faraday::ForbiddenError) do |ex|
|
43
45
|
expect(ex.message).to eq('the server responded with status 403')
|
44
46
|
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
47
|
+
expect(ex.response[:status]).to eq(403)
|
45
48
|
end
|
46
49
|
end
|
47
50
|
|
@@ -49,33 +52,39 @@ RSpec.describe Faraday::Response::RaiseError do
|
|
49
52
|
expect { conn.get('not-found') }.to raise_error(Faraday::ResourceNotFound) do |ex|
|
50
53
|
expect(ex.message).to eq('the server responded with status 404')
|
51
54
|
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
55
|
+
expect(ex.response[:status]).to eq(404)
|
52
56
|
end
|
53
57
|
end
|
54
58
|
|
55
|
-
it 'raises Faraday::
|
56
|
-
expect { conn.get('proxy-error') }.to raise_error(Faraday::
|
57
|
-
expect(ex.message).to eq('407 "Proxy Authentication Required
|
59
|
+
it 'raises Faraday::ProxyAuthError for 407 responses' do
|
60
|
+
expect { conn.get('proxy-error') }.to raise_error(Faraday::ProxyAuthError) do |ex|
|
61
|
+
expect(ex.message).to eq('407 "Proxy Authentication Required"')
|
58
62
|
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
63
|
+
expect(ex.response[:status]).to eq(407)
|
59
64
|
end
|
60
65
|
end
|
61
66
|
|
62
|
-
it 'raises Faraday::
|
63
|
-
expect { conn.get('conflict') }.to raise_error(Faraday::
|
67
|
+
it 'raises Faraday::ConflictError for 409 responses' do
|
68
|
+
expect { conn.get('conflict') }.to raise_error(Faraday::ConflictError) do |ex|
|
64
69
|
expect(ex.message).to eq('the server responded with status 409')
|
65
70
|
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
71
|
+
expect(ex.response[:status]).to eq(409)
|
66
72
|
end
|
67
73
|
end
|
68
74
|
|
69
|
-
it 'raises Faraday::
|
70
|
-
expect { conn.get('unprocessable-entity') }.to raise_error(Faraday::
|
75
|
+
it 'raises Faraday::UnprocessableEntityError for 422 responses' do
|
76
|
+
expect { conn.get('unprocessable-entity') }.to raise_error(Faraday::UnprocessableEntityError) do |ex|
|
71
77
|
expect(ex.message).to eq('the server responded with status 422')
|
72
78
|
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
79
|
+
expect(ex.response[:status]).to eq(422)
|
73
80
|
end
|
74
81
|
end
|
75
82
|
|
76
83
|
it 'raises Faraday::NilStatusError for nil status in response' do
|
77
84
|
expect { conn.get('nil-status') }.to raise_error(Faraday::NilStatusError) do |ex|
|
78
85
|
expect(ex.message).to eq('http status could not be derived from the server response')
|
86
|
+
expect(ex.response[:headers]['X-Reason']).to eq('nil')
|
87
|
+
expect(ex.response[:status]).to be_nil
|
79
88
|
end
|
80
89
|
end
|
81
90
|
|
@@ -83,13 +92,48 @@ RSpec.describe Faraday::Response::RaiseError do
|
|
83
92
|
expect { conn.get('4xx') }.to raise_error(Faraday::ClientError) do |ex|
|
84
93
|
expect(ex.message).to eq('the server responded with status 499')
|
85
94
|
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
95
|
+
expect(ex.response[:status]).to eq(499)
|
86
96
|
end
|
87
97
|
end
|
88
98
|
|
89
|
-
it 'raises Faraday::
|
90
|
-
expect { conn.get('server-error') }.to raise_error(Faraday::
|
99
|
+
it 'raises Faraday::ServerError for 500 responses' do
|
100
|
+
expect { conn.get('server-error') }.to raise_error(Faraday::ServerError) do |ex|
|
91
101
|
expect(ex.message).to eq('the server responded with status 500')
|
92
102
|
expect(ex.response[:headers]['X-Error']).to eq('bailout')
|
103
|
+
expect(ex.response[:status]).to eq(500)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe 'request info' do
|
108
|
+
let(:conn) do
|
109
|
+
Faraday.new do |b|
|
110
|
+
b.response :raise_error
|
111
|
+
b.adapter :test do |stub|
|
112
|
+
stub.post('request?full=true', request_body, request_headers) do
|
113
|
+
[400, { 'X-Reason' => 'because' }, 'keep looking']
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
let(:request_body) { JSON.generate({ 'item' => 'sth' }) }
|
119
|
+
let(:request_headers) { { 'Authorization' => 'Basic 123' } }
|
120
|
+
|
121
|
+
subject(:perform_request) do
|
122
|
+
conn.post 'request' do |req|
|
123
|
+
req.headers['Authorization'] = 'Basic 123'
|
124
|
+
req.params[:full] = true
|
125
|
+
req.body = request_body
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'returns the request info in the exception' do
|
130
|
+
expect { perform_request }.to raise_error(Faraday::BadRequestError) do |ex|
|
131
|
+
expect(ex.response[:request][:method]).to eq(:post)
|
132
|
+
expect(ex.response[:request][:url_path]).to eq('/request')
|
133
|
+
expect(ex.response[:request][:params]).to eq({ 'full' => 'true' })
|
134
|
+
expect(ex.response[:request][:headers]).to match(a_hash_including(request_headers))
|
135
|
+
expect(ex.response[:request][:body]).to eq(request_body)
|
136
|
+
end
|
93
137
|
end
|
94
138
|
end
|
95
139
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Faraday::Response do
|
4
|
+
subject { Faraday::Response.new(env) }
|
5
|
+
|
6
|
+
let(:env) do
|
7
|
+
Faraday::Env.from(status: 404, body: 'yikes',
|
8
|
+
response_headers: { 'Content-Type' => 'text/plain' })
|
9
|
+
end
|
10
|
+
|
11
|
+
it { expect(subject.finished?).to be_truthy }
|
12
|
+
it { expect { subject.finish({}) }.to raise_error(RuntimeError) }
|
13
|
+
it { expect(subject.success?).to be_falsey }
|
14
|
+
it { expect(subject.status).to eq(404) }
|
15
|
+
it { expect(subject.body).to eq('yikes') }
|
16
|
+
it { expect(subject.headers['Content-Type']).to eq('text/plain') }
|
17
|
+
it { expect(subject['content-type']).to eq('text/plain') }
|
18
|
+
|
19
|
+
describe '#apply_request' do
|
20
|
+
before { subject.apply_request(body: 'a=b', method: :post) }
|
21
|
+
|
22
|
+
it { expect(subject.body).to eq('yikes') }
|
23
|
+
it { expect(subject.env[:method]).to eq(:post) }
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#to_hash' do
|
27
|
+
let(:hash) { subject.to_hash }
|
28
|
+
|
29
|
+
it { expect(hash).to be_a(Hash) }
|
30
|
+
it { expect(hash[:status]).to eq(subject.status) }
|
31
|
+
it { expect(hash[:response_headers]).to eq(subject.headers) }
|
32
|
+
it { expect(hash[:body]).to eq(subject.body) }
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'marshal serialization support' do
|
36
|
+
subject { Faraday::Response.new }
|
37
|
+
let(:loaded) { Marshal.load(Marshal.dump(subject)) }
|
38
|
+
|
39
|
+
before do
|
40
|
+
subject.on_complete {}
|
41
|
+
subject.finish(env.merge(params: 'moo'))
|
42
|
+
end
|
43
|
+
|
44
|
+
it { expect(loaded.env[:params]).to be_nil }
|
45
|
+
it { expect(loaded.env[:body]).to eq(env[:body]) }
|
46
|
+
it { expect(loaded.env[:response_headers]).to eq(env[:response_headers]) }
|
47
|
+
it { expect(loaded.env[:status]).to eq(env[:status]) }
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#on_complete' do
|
51
|
+
subject { Faraday::Response.new }
|
52
|
+
|
53
|
+
it 'parse body on finish' do
|
54
|
+
subject.on_complete { |env| env[:body] = env[:body].upcase }
|
55
|
+
subject.finish(env)
|
56
|
+
|
57
|
+
expect(subject.body).to eq('YIKES')
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'can access response body in on_complete callback' do
|
61
|
+
subject.on_complete { |env| env[:body] = subject.body.upcase }
|
62
|
+
subject.finish(env)
|
63
|
+
|
64
|
+
expect(subject.body).to eq('YIKES')
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'can access response body in on_complete callback' do
|
68
|
+
callback_env = nil
|
69
|
+
subject.on_complete { |env| callback_env = env }
|
70
|
+
subject.finish({})
|
71
|
+
|
72
|
+
expect(subject.env).to eq(callback_env)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Faraday::Utils::Headers do
|
4
|
+
subject { Faraday::Utils::Headers.new }
|
5
|
+
|
6
|
+
context 'when Content-Type is set to application/json' do
|
7
|
+
before { subject['Content-Type'] = 'application/json' }
|
8
|
+
|
9
|
+
it { expect(subject.keys).to eq(['Content-Type']) }
|
10
|
+
it { expect(subject['Content-Type']).to eq('application/json') }
|
11
|
+
it { expect(subject['CONTENT-TYPE']).to eq('application/json') }
|
12
|
+
it { expect(subject['content-type']).to eq('application/json') }
|
13
|
+
it { is_expected.to include('content-type') }
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'when Content-Type is set to application/xml' do
|
17
|
+
before { subject['Content-Type'] = 'application/xml' }
|
18
|
+
|
19
|
+
it { expect(subject.keys).to eq(['Content-Type']) }
|
20
|
+
it { expect(subject['Content-Type']).to eq('application/xml') }
|
21
|
+
it { expect(subject['CONTENT-TYPE']).to eq('application/xml') }
|
22
|
+
it { expect(subject['content-type']).to eq('application/xml') }
|
23
|
+
it { is_expected.to include('content-type') }
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#fetch' do
|
27
|
+
before { subject['Content-Type'] = 'application/json' }
|
28
|
+
|
29
|
+
it { expect(subject.fetch('Content-Type')).to eq('application/json') }
|
30
|
+
it { expect(subject.fetch('CONTENT-TYPE')).to eq('application/json') }
|
31
|
+
it { expect(subject.fetch(:content_type)).to eq('application/json') }
|
32
|
+
it { expect(subject.fetch('invalid', 'default')).to eq('default') }
|
33
|
+
it { expect(subject.fetch('invalid', false)).to eq(false) }
|
34
|
+
it { expect(subject.fetch('invalid', nil)).to be_nil }
|
35
|
+
it { expect(subject.fetch('Invalid') { |key| "#{key} key" }).to eq('Invalid key') }
|
36
|
+
it 'calls a block when provided' do
|
37
|
+
block_called = false
|
38
|
+
expect(subject.fetch('content-type') { block_called = true }).to eq('application/json')
|
39
|
+
expect(block_called).to be_falsey
|
40
|
+
end
|
41
|
+
it 'raises an error if key not found' do
|
42
|
+
expected_error = defined?(KeyError) ? KeyError : IndexError
|
43
|
+
expect { subject.fetch('invalid') }.to raise_error(expected_error)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#delete' do
|
48
|
+
before do
|
49
|
+
subject['Content-Type'] = 'application/json'
|
50
|
+
@deleted = subject.delete('content-type')
|
51
|
+
end
|
52
|
+
|
53
|
+
it { expect(@deleted).to eq('application/json') }
|
54
|
+
it { expect(subject.size).to eq(0) }
|
55
|
+
it { is_expected.not_to include('content-type') }
|
56
|
+
it { expect(subject.delete('content-type')).to be_nil }
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#parse' do
|
60
|
+
before { subject.parse(headers) }
|
61
|
+
|
62
|
+
context 'when response headers leave http status line out' do
|
63
|
+
let(:headers) { "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n" }
|
64
|
+
|
65
|
+
it { expect(subject.keys).to eq(%w[Content-Type]) }
|
66
|
+
it { expect(subject['Content-Type']).to eq('text/html') }
|
67
|
+
it { expect(subject['content-type']).to eq('text/html') }
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'when response headers values include a colon' do
|
71
|
+
let(:headers) { "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nLocation: http://sushi.com/\r\n\r\n" }
|
72
|
+
|
73
|
+
it { expect(subject['location']).to eq('http://sushi.com/') }
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'when response headers include a blank line' do
|
77
|
+
let(:headers) { "HTTP/1.1 200 OK\r\n\r\nContent-Type: text/html\r\n\r\n" }
|
78
|
+
|
79
|
+
it { expect(subject['content-type']).to eq('text/html') }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Faraday::Utils do
|
4
|
+
describe 'headers parsing' do
|
5
|
+
let(:multi_response_headers) do
|
6
|
+
"HTTP/1.x 500 OK\r\nContent-Type: text/html; charset=UTF-8\r\n" \
|
7
|
+
"HTTP/1.x 200 OK\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n"
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'parse headers for aggregated responses' do
|
11
|
+
headers = Faraday::Utils::Headers.new
|
12
|
+
headers.parse(multi_response_headers)
|
13
|
+
|
14
|
+
result = headers.to_hash
|
15
|
+
|
16
|
+
expect(result['Content-Type']).to eq('application/json; charset=UTF-8')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'URI parsing' do
|
21
|
+
let(:url) { 'http://example.com/abc' }
|
22
|
+
|
23
|
+
it 'escapes safe buffer' do
|
24
|
+
str = FakeSafeBuffer.new('$32,000.00')
|
25
|
+
expect(Faraday::Utils.escape(str)).to eq('%2432%2C000.00')
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'parses with default parser' do
|
29
|
+
with_default_uri_parser(nil) do
|
30
|
+
uri = normalize(url)
|
31
|
+
expect(uri.host).to eq('example.com')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'parses with URI' do
|
36
|
+
with_default_uri_parser(::URI) do
|
37
|
+
uri = normalize(url)
|
38
|
+
expect(uri.host).to eq('example.com')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'parses with block' do
|
43
|
+
with_default_uri_parser(->(u) { "booya#{'!' * u.size}" }) do
|
44
|
+
expect(normalize(url)).to eq('booya!!!!!!!!!!!!!!!!!!!!!!')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'replaces headers hash' do
|
49
|
+
headers = Faraday::Utils::Headers.new('authorization' => 't0ps3cr3t!')
|
50
|
+
expect(headers).to have_key('authorization')
|
51
|
+
|
52
|
+
headers.replace('content-type' => 'text/plain')
|
53
|
+
expect(headers).not_to have_key('authorization')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Faraday do
|
4
|
+
it 'has a version number' do
|
5
|
+
expect(Faraday::VERSION).not_to be nil
|
6
|
+
end
|
7
|
+
|
8
|
+
context 'proxies to default_connection' do
|
9
|
+
let(:mock_connection) { double('Connection') }
|
10
|
+
before do
|
11
|
+
Faraday.default_connection = mock_connection
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'proxies methods that exist on the default_connection' do
|
15
|
+
expect(mock_connection).to receive(:this_should_be_proxied)
|
16
|
+
|
17
|
+
Faraday.this_should_be_proxied
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'uses method_missing on Faraday if there is no proxyable method' do
|
21
|
+
expect { Faraday.this_method_does_not_exist }.to raise_error(
|
22
|
+
NoMethodError,
|
23
|
+
"undefined method `this_method_does_not_exist' for Faraday:Module"
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'proxied methods can be accessed' do
|
28
|
+
allow(mock_connection).to receive(:this_should_be_proxied)
|
29
|
+
|
30
|
+
expect(Faraday.method(:this_should_be_proxied)).to be_a(Method)
|
31
|
+
end
|
32
|
+
|
33
|
+
after do
|
34
|
+
Faraday.default_connection = nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|