faraday 1.10.4 → 2.13.4
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 +198 -4
- data/LICENSE.md +1 -1
- data/README.md +34 -20
- data/Rakefile +6 -1
- data/examples/client_spec.rb +41 -19
- data/examples/client_test.rb +48 -22
- data/lib/faraday/adapter/test.rb +62 -13
- data/lib/faraday/adapter.rb +6 -10
- data/lib/faraday/connection.rb +72 -150
- data/lib/faraday/encoders/nested_params_encoder.rb +14 -7
- data/lib/faraday/error.rb +62 -9
- data/lib/faraday/logging/formatter.rb +29 -16
- data/lib/faraday/middleware.rb +43 -2
- 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 -5
- data/lib/faraday/options/request_options.rb +7 -6
- data/lib/faraday/options/ssl_options.rb +62 -45
- data/lib/faraday/options.rb +7 -6
- data/lib/faraday/rack_builder.rb +44 -45
- data/lib/faraday/request/authorization.rb +33 -41
- data/lib/faraday/request/instrumentation.rb +5 -1
- data/lib/faraday/request/json.rb +18 -3
- data/lib/faraday/request/url_encoded.rb +5 -1
- data/lib/faraday/request.rb +15 -30
- data/lib/faraday/response/json.rb +25 -5
- data/lib/faraday/response/logger.rb +11 -3
- data/lib/faraday/response/raise_error.rb +45 -18
- data/lib/faraday/response.rb +9 -21
- data/lib/faraday/utils/headers.rb +15 -4
- data/lib/faraday/utils.rb +11 -7
- data/lib/faraday/version.rb +1 -1
- data/lib/faraday.rb +10 -45
- data/spec/faraday/adapter/test_spec.rb +65 -0
- data/spec/faraday/connection_spec.rb +165 -93
- data/spec/faraday/error_spec.rb +122 -7
- data/spec/faraday/middleware_registry_spec.rb +31 -0
- data/spec/faraday/middleware_spec.rb +161 -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 +35 -0
- data/spec/faraday/params_encoders/nested_spec.rb +10 -1
- data/spec/faraday/rack_builder_spec.rb +26 -54
- data/spec/faraday/request/authorization_spec.rb +50 -28
- data/spec/faraday/request/instrumentation_spec.rb +5 -7
- data/spec/faraday/request/json_spec.rb +88 -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 +93 -6
- data/spec/faraday/response/logger_spec.rb +77 -4
- data/spec/faraday/response/raise_error_spec.rb +119 -13
- data/spec/faraday/response_spec.rb +3 -1
- data/spec/faraday/utils/headers_spec.rb +31 -4
- data/spec/faraday/utils_spec.rb +65 -1
- data/spec/faraday_spec.rb +10 -4
- data/spec/spec_helper.rb +5 -6
- data/spec/support/fake_safe_buffer.rb +1 -1
- data/spec/support/faraday_middleware_subclasses.rb +18 -0
- 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 +24 -149
- data/lib/faraday/adapter/typhoeus.rb +0 -15
- data/lib/faraday/autoload.rb +0 -89
- data/lib/faraday/dependency_loader.rb +0 -39
- data/lib/faraday/deprecate.rb +0 -110
- data/lib/faraday/request/basic_authentication.rb +0 -20
- data/lib/faraday/request/token_authentication.rb +0 -20
- data/spec/faraday/adapter/em_http_spec.rb +0 -49
- data/spec/faraday/adapter/em_synchrony_spec.rb +0 -18
- 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/deprecate_spec.rb +0 -147
- data/spec/faraday/response/middleware_spec.rb +0 -68
- data/spec/support/webmock_rack_app.rb +0 -68
@@ -3,7 +3,7 @@
|
|
3
3
|
RSpec.describe Faraday::Request::Authorization do
|
4
4
|
let(:conn) do
|
5
5
|
Faraday.new do |b|
|
6
|
-
b.request auth_type, *auth_config
|
6
|
+
b.request :authorization, auth_type, *auth_config
|
7
7
|
b.adapter :test do |stub|
|
8
8
|
stub.get('/auth-echo') do |env|
|
9
9
|
[200, {}, env[:request_headers]['Authorization']]
|
@@ -14,10 +14,10 @@ RSpec.describe Faraday::Request::Authorization do
|
|
14
14
|
|
15
15
|
shared_examples 'does not interfere with existing authentication' do
|
16
16
|
context 'and request already has an authentication header' do
|
17
|
-
let(:response) { conn.get('/auth-echo', nil, authorization: '
|
17
|
+
let(:response) { conn.get('/auth-echo', nil, authorization: 'OAuth oauth_token') }
|
18
18
|
|
19
19
|
it 'does not interfere with existing authorization' do
|
20
|
-
expect(response.body).to eq('
|
20
|
+
expect(response.body).to eq('OAuth oauth_token')
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
@@ -25,7 +25,7 @@ RSpec.describe Faraday::Request::Authorization do
|
|
25
25
|
let(:response) { conn.get('/auth-echo') }
|
26
26
|
|
27
27
|
describe 'basic_auth' do
|
28
|
-
let(:auth_type) { :
|
28
|
+
let(:auth_type) { :basic }
|
29
29
|
|
30
30
|
context 'when passed correct params' do
|
31
31
|
let(:auth_config) { %w[aladdin opensesame] }
|
@@ -44,51 +44,73 @@ RSpec.describe Faraday::Request::Authorization do
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
describe '
|
48
|
-
let(:auth_type) { :
|
47
|
+
describe 'authorization' do
|
48
|
+
let(:auth_type) { :Bearer }
|
49
49
|
|
50
|
-
context 'when passed
|
51
|
-
let(:auth_config) { '
|
50
|
+
context 'when passed a string' do
|
51
|
+
let(:auth_config) { ['custom'] }
|
52
52
|
|
53
|
-
it { expect(response.body).to eq('
|
53
|
+
it { expect(response.body).to eq('Bearer custom') }
|
54
54
|
|
55
55
|
include_examples 'does not interfere with existing authentication'
|
56
56
|
end
|
57
57
|
|
58
|
-
context 'when
|
59
|
-
let(:auth_config) { [
|
58
|
+
context 'when passed a proc' do
|
59
|
+
let(:auth_config) { [-> { 'custom_from_proc' }] }
|
60
60
|
|
61
|
-
it { expect(response.body).to
|
62
|
-
it { expect(response.body).to match(/token="baz"/) }
|
63
|
-
it { expect(response.body).to match(/foo="42"/) }
|
61
|
+
it { expect(response.body).to eq('Bearer custom_from_proc') }
|
64
62
|
|
65
63
|
include_examples 'does not interfere with existing authentication'
|
66
64
|
end
|
67
|
-
end
|
68
|
-
|
69
|
-
describe 'authorization' do
|
70
|
-
let(:auth_type) { :authorization }
|
71
65
|
|
72
|
-
context 'when passed
|
73
|
-
let(:
|
66
|
+
context 'when passed a callable' do
|
67
|
+
let(:callable) { double('Callable Authorizer', call: 'custom_from_callable') }
|
68
|
+
let(:auth_config) { [callable] }
|
74
69
|
|
75
|
-
it { expect(response.body).to eq('
|
70
|
+
it { expect(response.body).to eq('Bearer custom_from_callable') }
|
76
71
|
|
77
72
|
include_examples 'does not interfere with existing authentication'
|
78
73
|
end
|
79
74
|
|
80
|
-
context '
|
81
|
-
let(:
|
75
|
+
context 'with an argument' do
|
76
|
+
let(:response) { conn.get('/auth-echo', nil, 'middle' => 'crunchy surprise') }
|
82
77
|
|
83
|
-
|
78
|
+
context 'when passed a proc' do
|
79
|
+
let(:auth_config) { [proc { |env| "proc #{env.request_headers['middle']}" }] }
|
84
80
|
|
85
|
-
|
81
|
+
it { expect(response.body).to eq('Bearer proc crunchy surprise') }
|
82
|
+
|
83
|
+
include_examples 'does not interfere with existing authentication'
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'when passed a lambda' do
|
87
|
+
let(:auth_config) { [->(env) { "lambda #{env.request_headers['middle']}" }] }
|
88
|
+
|
89
|
+
it { expect(response.body).to eq('Bearer lambda crunchy surprise') }
|
90
|
+
|
91
|
+
include_examples 'does not interfere with existing authentication'
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'when passed a callable with an argument' do
|
95
|
+
let(:callable) do
|
96
|
+
Class.new do
|
97
|
+
def call(env)
|
98
|
+
"callable #{env.request_headers['middle']}"
|
99
|
+
end
|
100
|
+
end.new
|
101
|
+
end
|
102
|
+
let(:auth_config) { [callable] }
|
103
|
+
|
104
|
+
it { expect(response.body).to eq('Bearer callable crunchy surprise') }
|
105
|
+
|
106
|
+
include_examples 'does not interfere with existing authentication'
|
107
|
+
end
|
86
108
|
end
|
87
109
|
|
88
|
-
context 'when passed
|
89
|
-
let(:auth_config) { [
|
110
|
+
context 'when passed too many arguments' do
|
111
|
+
let(:auth_config) { %w[baz foo] }
|
90
112
|
|
91
|
-
it { expect
|
113
|
+
it { expect { response }.to raise_error(ArgumentError) }
|
92
114
|
|
93
115
|
include_examples 'does not interfere with existing authentication'
|
94
116
|
end
|
@@ -30,13 +30,11 @@ RSpec.describe Faraday::Request::Instrumentation do
|
|
30
30
|
|
31
31
|
it { expect(options.name).to eq('request.faraday') }
|
32
32
|
it 'defaults to ActiveSupport::Notifications' do
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
expect(res).to eq(ActiveSupport::Notifications)
|
39
|
-
end
|
33
|
+
res = options.instrumenter
|
34
|
+
rescue NameError => e
|
35
|
+
expect(e.to_s).to match('ActiveSupport')
|
36
|
+
else
|
37
|
+
expect(res).to eq(ActiveSupport::Notifications)
|
40
38
|
end
|
41
39
|
|
42
40
|
it 'instruments with default name' do
|
@@ -73,6 +73,30 @@ RSpec.describe Faraday::Request::Json do
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
+
context 'true body' do
|
77
|
+
let(:result) { process(true) }
|
78
|
+
|
79
|
+
it 'encodes body' do
|
80
|
+
expect(result_body).to eq('true')
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'adds content type' do
|
84
|
+
expect(result_type).to eq('application/json')
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'false body' do
|
89
|
+
let(:result) { process(false) }
|
90
|
+
|
91
|
+
it 'encodes body' do
|
92
|
+
expect(result_body).to eq('false')
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'adds content type' do
|
96
|
+
expect(result_type).to eq('application/json')
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
76
100
|
context 'object body with json type' do
|
77
101
|
let(:result) { process({ a: 1 }, 'application/json; charset=utf-8') }
|
78
102
|
|
@@ -108,4 +132,68 @@ RSpec.describe Faraday::Request::Json do
|
|
108
132
|
expect(result_type).to eq('application/xml; charset=utf-8')
|
109
133
|
end
|
110
134
|
end
|
135
|
+
|
136
|
+
context 'with encoder' do
|
137
|
+
let(:encoder) do
|
138
|
+
double('Encoder').tap do |e|
|
139
|
+
allow(e).to receive(:dump) { |s, opts| JSON.generate(s, opts) }
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
let(:result) { process(a: 1) }
|
144
|
+
|
145
|
+
context 'when encoder is passed as object' do
|
146
|
+
let(:middleware) { described_class.new(->(env) { Faraday::Response.new(env) }, { encoder: encoder }) }
|
147
|
+
|
148
|
+
it 'calls specified JSON encoder\'s dump method' do
|
149
|
+
expect(encoder).to receive(:dump).with({ a: 1 })
|
150
|
+
|
151
|
+
result
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'encodes body' do
|
155
|
+
expect(result_body).to eq('{"a":1}')
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'adds content type' do
|
159
|
+
expect(result_type).to eq('application/json')
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context 'when encoder is passed as an object-method pair' do
|
164
|
+
let(:middleware) { described_class.new(->(env) { Faraday::Response.new(env) }, { encoder: [encoder, :dump] }) }
|
165
|
+
|
166
|
+
it 'calls specified JSON encoder' do
|
167
|
+
expect(encoder).to receive(:dump).with({ a: 1 })
|
168
|
+
|
169
|
+
result
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'encodes body' do
|
173
|
+
expect(result_body).to eq('{"a":1}')
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'adds content type' do
|
177
|
+
expect(result_type).to eq('application/json')
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
context 'when encoder is not passed' do
|
182
|
+
let(:middleware) { described_class.new(->(env) { Faraday::Response.new(env) }) }
|
183
|
+
|
184
|
+
it 'calls JSON.generate' do
|
185
|
+
expect(JSON).to receive(:generate).with({ a: 1 })
|
186
|
+
|
187
|
+
result
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'encodes body' do
|
191
|
+
expect(result_body).to eq('{"a":1}')
|
192
|
+
end
|
193
|
+
|
194
|
+
it 'adds content type' do
|
195
|
+
expect(result_type).to eq('application/json')
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
111
199
|
end
|
@@ -1,14 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'stringio'
|
4
|
+
|
3
5
|
RSpec.describe Faraday::Request::UrlEncoded do
|
4
6
|
let(:conn) do
|
5
7
|
Faraday.new do |b|
|
6
|
-
b.request :multipart
|
7
8
|
b.request :url_encoded
|
8
9
|
b.adapter :test do |stub|
|
9
10
|
stub.post('/echo') do |env|
|
10
11
|
posted_as = env[:request_headers]['Content-Type']
|
11
|
-
|
12
|
+
body = env[:body]
|
13
|
+
if body.respond_to?(:read)
|
14
|
+
body = body.read
|
15
|
+
end
|
16
|
+
[200, { 'Content-Type' => posted_as }, body]
|
12
17
|
end
|
13
18
|
end
|
14
19
|
end
|
@@ -68,6 +73,11 @@ RSpec.describe Faraday::Request::UrlEncoded do
|
|
68
73
|
expect(response.body).to eq('a%5Bb%5D%5Bc%5D%5B%5D=d')
|
69
74
|
end
|
70
75
|
|
76
|
+
it 'works with files' do
|
77
|
+
response = conn.post('/echo', StringIO.new('str=apple'))
|
78
|
+
expect(response.body).to eq('str=apple')
|
79
|
+
end
|
80
|
+
|
71
81
|
context 'customising default_space_encoding' do
|
72
82
|
around do |example|
|
73
83
|
Faraday::Utils.default_space_encoding = '%20'
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
RSpec.describe Faraday::Request do
|
4
4
|
let(:conn) do
|
5
|
-
Faraday.new(url: 'http://
|
5
|
+
Faraday.new(url: 'http://httpbingo.org/api',
|
6
6
|
headers: { 'Mime-Version' => '1.0' },
|
7
7
|
request: { oauth: { consumer_key: 'anonymous' } })
|
8
8
|
end
|
@@ -14,6 +14,7 @@ RSpec.describe Faraday::Request do
|
|
14
14
|
context 'when nothing particular is configured' do
|
15
15
|
it { expect(subject.http_method).to eq(:get) }
|
16
16
|
it { expect(subject.to_env(conn).ssl.verify).to be_falsey }
|
17
|
+
it { expect(subject.to_env(conn).ssl.verify_hostname).to be_falsey }
|
17
18
|
end
|
18
19
|
|
19
20
|
context 'when HTTP method is post' do
|
@@ -22,23 +23,12 @@ RSpec.describe Faraday::Request do
|
|
22
23
|
it { expect(subject.http_method).to eq(:post) }
|
23
24
|
end
|
24
25
|
|
25
|
-
describe 'deprecate method for HTTP method' do
|
26
|
-
let(:http_method) { :post }
|
27
|
-
let(:expected_warning) do
|
28
|
-
%r{NOTE: Faraday::Request#method is deprecated; use http_method instead\. It will be removed in or after version 2.0 \nFaraday::Request#method called from .+/spec/faraday/request_spec.rb:\d+.}
|
29
|
-
end
|
30
|
-
|
31
|
-
it { expect(subject.method).to eq(:post) }
|
32
|
-
|
33
|
-
it { expect { subject.method }.to output(expected_warning).to_stderr }
|
34
|
-
end
|
35
|
-
|
36
26
|
context 'when setting the url on setup with a URI' do
|
37
27
|
let(:block) { proc { |req| req.url URI.parse('foo.json?a=1') } }
|
38
28
|
|
39
29
|
it { expect(subject.path).to eq(URI.parse('foo.json')) }
|
40
30
|
it { expect(subject.params).to eq('a' => '1') }
|
41
|
-
it { expect(subject.to_env(conn).url.to_s).to eq('http://
|
31
|
+
it { expect(subject.to_env(conn).url.to_s).to eq('http://httpbingo.org/api/foo.json?a=1') }
|
42
32
|
end
|
43
33
|
|
44
34
|
context 'when setting the url on setup with a string path and params' do
|
@@ -46,7 +36,7 @@ RSpec.describe Faraday::Request do
|
|
46
36
|
|
47
37
|
it { expect(subject.path).to eq('foo.json') }
|
48
38
|
it { expect(subject.params).to eq('a' => 1) }
|
49
|
-
it { expect(subject.to_env(conn).url.to_s).to eq('http://
|
39
|
+
it { expect(subject.to_env(conn).url.to_s).to eq('http://httpbingo.org/api/foo.json?a=1') }
|
50
40
|
end
|
51
41
|
|
52
42
|
context 'when setting the url on setup with a path including params' do
|
@@ -54,7 +44,7 @@ RSpec.describe Faraday::Request do
|
|
54
44
|
|
55
45
|
it { expect(subject.path).to eq('foo.json') }
|
56
46
|
it { expect(subject.params).to eq('a' => '1', 'b' => '2') }
|
57
|
-
it { expect(subject.to_env(conn).url.to_s).to eq('http://
|
47
|
+
it { expect(subject.to_env(conn).url.to_s).to eq('http://httpbingo.org/api/foo.json?a=1&b=2') }
|
58
48
|
end
|
59
49
|
|
60
50
|
context 'when setting a header on setup with []= syntax' do
|
@@ -76,12 +76,10 @@ RSpec.describe Faraday::Response::Json, type: :response do
|
|
76
76
|
end
|
77
77
|
|
78
78
|
it 'includes the response on the ParsingError instance' do
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
expect(e.response).to be_a(Faraday::Response)
|
84
|
-
end
|
79
|
+
process('{') { |env| env[:response] = Faraday::Response.new }
|
80
|
+
raise 'Parsing should have failed.'
|
81
|
+
rescue Faraday::ParsingError => e
|
82
|
+
expect(e.response).to be_a(Faraday::Response)
|
85
83
|
end
|
86
84
|
|
87
85
|
context 'HEAD responses' do
|
@@ -116,4 +114,93 @@ RSpec.describe Faraday::Response::Json, type: :response do
|
|
116
114
|
expect(response.body).to eq(result)
|
117
115
|
end
|
118
116
|
end
|
117
|
+
|
118
|
+
context 'with decoder' do
|
119
|
+
let(:decoder) do
|
120
|
+
double('Decoder').tap do |e|
|
121
|
+
allow(e).to receive(:load) { |s, opts| JSON.parse(s, opts) }
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
let(:body) { '{"a": 1}' }
|
126
|
+
let(:result) { { a: 1 } }
|
127
|
+
|
128
|
+
context 'when decoder is passed as object' do
|
129
|
+
let(:options) do
|
130
|
+
{
|
131
|
+
parser_options: {
|
132
|
+
decoder: decoder,
|
133
|
+
option: :option_value,
|
134
|
+
symbolize_names: true
|
135
|
+
}
|
136
|
+
}
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'passes relevant options to specified decoder\'s load method' do
|
140
|
+
expect(decoder).to receive(:load)
|
141
|
+
.with(body, { option: :option_value, symbolize_names: true })
|
142
|
+
.and_return(result)
|
143
|
+
|
144
|
+
response = process(body)
|
145
|
+
expect(response.body).to eq(result)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
context 'when decoder is passed as an object-method pair' do
|
150
|
+
let(:options) do
|
151
|
+
{
|
152
|
+
parser_options: {
|
153
|
+
decoder: [decoder, :load],
|
154
|
+
option: :option_value,
|
155
|
+
symbolize_names: true
|
156
|
+
}
|
157
|
+
}
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'passes relevant options to specified decoder\'s method' do
|
161
|
+
expect(decoder).to receive(:load)
|
162
|
+
.with(body, { option: :option_value, symbolize_names: true })
|
163
|
+
.and_return(result)
|
164
|
+
|
165
|
+
response = process(body)
|
166
|
+
expect(response.body).to eq(result)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
context 'when decoder is not passed' do
|
171
|
+
let(:options) do
|
172
|
+
{
|
173
|
+
parser_options: {
|
174
|
+
symbolize_names: true
|
175
|
+
}
|
176
|
+
}
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'passes relevant options to JSON parse' do
|
180
|
+
expect(JSON).to receive(:parse)
|
181
|
+
.with(body, { symbolize_names: true })
|
182
|
+
.and_return(result)
|
183
|
+
|
184
|
+
response = process(body)
|
185
|
+
expect(response.body).to eq(result)
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'passes relevant options to JSON parse even when nil responds to :load' do
|
189
|
+
original_allow_message_expectations_on_nil = RSpec::Mocks.configuration.allow_message_expectations_on_nil
|
190
|
+
RSpec::Mocks.configuration.allow_message_expectations_on_nil = true
|
191
|
+
allow(nil).to receive(:respond_to?)
|
192
|
+
.with(:load)
|
193
|
+
.and_return(true)
|
194
|
+
|
195
|
+
expect(JSON).to receive(:parse)
|
196
|
+
.with(body, { symbolize_names: true })
|
197
|
+
.and_return(result)
|
198
|
+
|
199
|
+
response = process(body)
|
200
|
+
expect(response.body).to eq(result)
|
201
|
+
ensure
|
202
|
+
RSpec::Mocks.configuration.allow_message_expectations_on_nil = original_allow_message_expectations_on_nil
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
119
206
|
end
|
@@ -25,6 +25,7 @@ RSpec.describe Faraday::Response::Logger do
|
|
25
25
|
stubs.get('/filtered_headers') { [200, { 'Content-Type' => 'text/html' }, 'headers response'] }
|
26
26
|
stubs.get('/filtered_params') { [200, { 'Content-Type' => 'text/html' }, 'params response'] }
|
27
27
|
stubs.get('/filtered_url') { [200, { 'Content-Type' => 'text/html' }, 'url response'] }
|
28
|
+
stubs.get('/connection_failed') { raise Faraday::ConnectionFailed, 'Failed to open TCP connection' }
|
28
29
|
end
|
29
30
|
end
|
30
31
|
end
|
@@ -54,6 +55,26 @@ RSpec.describe Faraday::Response::Logger do
|
|
54
55
|
end
|
55
56
|
end
|
56
57
|
|
58
|
+
context 'when logger with program name' do
|
59
|
+
let(:logger) { Logger.new(string_io, progname: 'my_best_program') }
|
60
|
+
|
61
|
+
it 'logs with program name' do
|
62
|
+
conn.get '/hello'
|
63
|
+
|
64
|
+
expect(string_io.string).to match('-- my_best_program: request:')
|
65
|
+
expect(string_io.string).to match('-- my_best_program: response:')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'when logger without program name' do
|
70
|
+
it 'logs without program name' do
|
71
|
+
conn.get '/hello'
|
72
|
+
|
73
|
+
expect(string_io.string).to match('-- : request:')
|
74
|
+
expect(string_io.string).to match('-- : response:')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
57
78
|
context 'with default formatter' do
|
58
79
|
let(:formatter) { instance_double(Faraday::Logging::Formatter, request: true, response: true, filter: []) }
|
59
80
|
|
@@ -64,6 +85,15 @@ RSpec.describe Faraday::Response::Logger do
|
|
64
85
|
expect(formatter).to receive(:response).with(an_instance_of(Faraday::Env))
|
65
86
|
conn.get '/hello'
|
66
87
|
end
|
88
|
+
|
89
|
+
context 'when no route' do
|
90
|
+
it 'delegates logging to the formatter' do
|
91
|
+
expect(formatter).to receive(:request).with(an_instance_of(Faraday::Env))
|
92
|
+
expect(formatter).to receive(:exception).with(an_instance_of(Faraday::Adapter::Test::Stubs::NotFound))
|
93
|
+
|
94
|
+
expect { conn.get '/noroute' }.to raise_error(Faraday::Adapter::Test::Stubs::NotFound)
|
95
|
+
end
|
96
|
+
end
|
67
97
|
end
|
68
98
|
|
69
99
|
context 'with custom formatter' do
|
@@ -94,6 +124,16 @@ RSpec.describe Faraday::Response::Logger do
|
|
94
124
|
expect(string_io.string).to match('GET http:/hello')
|
95
125
|
end
|
96
126
|
|
127
|
+
it 'logs status' do
|
128
|
+
conn.get '/hello', nil, accept: 'text/html'
|
129
|
+
expect(string_io.string).to match('Status 200')
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'does not log error message by default' do
|
133
|
+
expect { conn.get '/noroute' }.to raise_error(Faraday::Adapter::Test::Stubs::NotFound)
|
134
|
+
expect(string_io.string).not_to match(%(no stubbed request for get http:/noroute))
|
135
|
+
end
|
136
|
+
|
97
137
|
it 'logs request headers by default' do
|
98
138
|
conn.get '/hello', nil, accept: 'text/html'
|
99
139
|
expect(string_io.string).to match(%(Accept: "text/html))
|
@@ -149,7 +189,7 @@ RSpec.describe Faraday::Response::Logger do
|
|
149
189
|
context 'when logging request body' do
|
150
190
|
let(:logger_options) { { bodies: { request: true } } }
|
151
191
|
|
152
|
-
it '
|
192
|
+
it 'logs only request body' do
|
153
193
|
conn.post '/ohyes', 'name=Tamago', accept: 'text/html'
|
154
194
|
expect(string_io.string).to match(%(name=Tamago))
|
155
195
|
expect(string_io.string).not_to match(%(pebbles))
|
@@ -159,7 +199,7 @@ RSpec.describe Faraday::Response::Logger do
|
|
159
199
|
context 'when logging response body' do
|
160
200
|
let(:logger_options) { { bodies: { response: true } } }
|
161
201
|
|
162
|
-
it '
|
202
|
+
it 'logs only response body' do
|
163
203
|
conn.post '/ohyes', 'name=Hamachi', accept: 'text/html'
|
164
204
|
expect(string_io.string).to match(%(pebbles))
|
165
205
|
expect(string_io.string).not_to match(%(name=Hamachi))
|
@@ -169,13 +209,13 @@ RSpec.describe Faraday::Response::Logger do
|
|
169
209
|
context 'when logging request and response bodies' do
|
170
210
|
let(:logger_options) { { bodies: true } }
|
171
211
|
|
172
|
-
it '
|
212
|
+
it 'logs request and response body' do
|
173
213
|
conn.post '/ohyes', 'name=Ebi', accept: 'text/html'
|
174
214
|
expect(string_io.string).to match(%(name=Ebi))
|
175
215
|
expect(string_io.string).to match(%(pebbles))
|
176
216
|
end
|
177
217
|
|
178
|
-
it '
|
218
|
+
it 'logs response body object' do
|
179
219
|
conn.get '/rubbles', nil, accept: 'text/html'
|
180
220
|
expect(string_io.string).to match(%([\"Barney\", \"Betty\", \"Bam Bam\"]\n))
|
181
221
|
end
|
@@ -188,6 +228,39 @@ RSpec.describe Faraday::Response::Logger do
|
|
188
228
|
end
|
189
229
|
end
|
190
230
|
|
231
|
+
context 'when bodies are logged by default' do
|
232
|
+
before do
|
233
|
+
described_class.default_options = { bodies: true }
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'logs response body' do
|
237
|
+
conn.post '/ohai'
|
238
|
+
expect(string_io.string).to match(%(fred))
|
239
|
+
end
|
240
|
+
|
241
|
+
after do
|
242
|
+
described_class.default_options = { bodies: false }
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
context 'when logging errors' do
|
247
|
+
let(:logger_options) { { errors: true } }
|
248
|
+
|
249
|
+
it 'logs error message' do
|
250
|
+
expect { conn.get '/noroute' }.to raise_error(Faraday::Adapter::Test::Stubs::NotFound)
|
251
|
+
expect(string_io.string).to match(%(no stubbed request for get http:/noroute))
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
context 'when logging headers and errors' do
|
256
|
+
let(:logger_options) { { headers: true, errors: true } }
|
257
|
+
|
258
|
+
it 'logs error message' do
|
259
|
+
expect { conn.get '/connection_failed' }.to raise_error(Faraday::ConnectionFailed)
|
260
|
+
expect(string_io.string).to match(%(Failed to open TCP connection))
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
191
264
|
context 'when using log_level' do
|
192
265
|
let(:logger_options) { { bodies: true, log_level: :debug } }
|
193
266
|
|