faraday 2.8.1 → 2.14.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 +1 -1
- data/README.md +1 -1
- data/Rakefile +3 -0
- data/lib/faraday/adapter.rb +1 -1
- data/lib/faraday/connection.rb +16 -7
- data/lib/faraday/encoders/flat_params_encoder.rb +2 -2
- data/lib/faraday/encoders/nested_params_encoder.rb +1 -1
- data/lib/faraday/error.rb +46 -5
- data/lib/faraday/logging/formatter.rb +7 -7
- data/lib/faraday/middleware.rb +40 -1
- data/lib/faraday/options/env.rb +2 -2
- data/lib/faraday/options/proxy_options.rb +4 -2
- data/lib/faraday/options/ssl_options.rb +8 -2
- data/lib/faraday/rack_builder.rb +21 -25
- data/lib/faraday/request/json.rb +1 -1
- data/lib/faraday/response/json.rb +2 -1
- data/lib/faraday/response/logger.rb +5 -3
- data/lib/faraday/response/raise_error.rb +19 -19
- data/lib/faraday/response.rb +7 -3
- data/lib/faraday/utils/headers.rb +8 -2
- data/lib/faraday/utils.rb +3 -4
- data/lib/faraday/version.rb +1 -1
- data/lib/faraday.rb +2 -1
- data/spec/faraday/connection_spec.rb +2 -2
- data/spec/faraday/error_spec.rb +93 -3
- data/spec/faraday/middleware_spec.rb +143 -0
- data/spec/faraday/options/proxy_options_spec.rb +27 -0
- data/spec/faraday/params_encoders/nested_spec.rb +2 -1
- data/spec/faraday/response/json_spec.rb +17 -0
- data/spec/faraday/response/logger_spec.rb +45 -4
- data/spec/faraday/response/raise_error_spec.rb +97 -22
- data/spec/faraday/response_spec.rb +7 -0
- data/spec/faraday/utils/headers_spec.rb +9 -0
- data/spec/faraday/utils_spec.rb +3 -1
- data/spec/faraday_spec.rb +3 -1
- data/spec/spec_helper.rb +6 -5
- data/spec/support/faraday_middleware_subclasses.rb +18 -0
- metadata +22 -24
data/lib/faraday/utils.rb
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'base64'
|
|
4
3
|
require 'uri'
|
|
5
4
|
require 'faraday/utils/headers'
|
|
6
5
|
require 'faraday/utils/params_hash'
|
|
@@ -26,7 +25,7 @@ module Faraday
|
|
|
26
25
|
attr_writer :default_space_encoding
|
|
27
26
|
end
|
|
28
27
|
|
|
29
|
-
ESCAPE_RE = /[^a-zA-Z0-9 .~_-]
|
|
28
|
+
ESCAPE_RE = /[^a-zA-Z0-9 .~_-]/
|
|
30
29
|
|
|
31
30
|
def escape(str)
|
|
32
31
|
str.to_s.gsub(ESCAPE_RE) do |match|
|
|
@@ -38,7 +37,7 @@ module Faraday
|
|
|
38
37
|
CGI.unescape str.to_s
|
|
39
38
|
end
|
|
40
39
|
|
|
41
|
-
DEFAULT_SEP = /[&;] */n
|
|
40
|
+
DEFAULT_SEP = /[&;] */n
|
|
42
41
|
|
|
43
42
|
# Adapted from Rack
|
|
44
43
|
def parse_query(query)
|
|
@@ -54,7 +53,7 @@ module Faraday
|
|
|
54
53
|
end
|
|
55
54
|
|
|
56
55
|
def basic_header_from(login, pass)
|
|
57
|
-
value =
|
|
56
|
+
value = ["#{login}:#{pass}"].pack('m') # Base64 encoding
|
|
58
57
|
value.delete!("\n")
|
|
59
58
|
"Basic #{value}"
|
|
60
59
|
end
|
data/lib/faraday/version.rb
CHANGED
data/lib/faraday.rb
CHANGED
|
@@ -300,14 +300,14 @@ RSpec.describe Faraday::Connection do
|
|
|
300
300
|
it 'joins url to base when used relative path' do
|
|
301
301
|
conn = Faraday.new(url: url)
|
|
302
302
|
uri = conn.build_exclusive_url('service:search?limit=400')
|
|
303
|
-
expect(uri.to_s).to eq('http://service.com/service
|
|
303
|
+
expect(uri.to_s).to eq('http://service.com/service:search?limit=400')
|
|
304
304
|
end
|
|
305
305
|
|
|
306
306
|
it 'joins url to base when used with path prefix' do
|
|
307
307
|
conn = Faraday.new(url: url)
|
|
308
308
|
conn.path_prefix = '/api'
|
|
309
309
|
uri = conn.build_exclusive_url('service:search?limit=400')
|
|
310
|
-
expect(uri.to_s).to eq('http://service.com/api/service
|
|
310
|
+
expect(uri.to_s).to eq('http://service.com/api/service:search?limit=400')
|
|
311
311
|
end
|
|
312
312
|
end
|
|
313
313
|
|
data/spec/faraday/error_spec.rb
CHANGED
|
@@ -23,8 +23,12 @@ RSpec.describe Faraday::Error do
|
|
|
23
23
|
|
|
24
24
|
it { expect(subject.wrapped_exception).to be_nil }
|
|
25
25
|
it { expect(subject.response).to eq(exception) }
|
|
26
|
-
it { expect(subject.message).to eq('the server responded with status 400') }
|
|
27
|
-
|
|
26
|
+
it { expect(subject.message).to eq('the server responded with status 400 - method and url are not available due to include_request: false on Faraday::Response::RaiseError middleware') }
|
|
27
|
+
if RUBY_VERSION >= '3.4'
|
|
28
|
+
it { expect(subject.inspect).to eq('#<Faraday::Error response={status: 400}>') }
|
|
29
|
+
else
|
|
30
|
+
it { expect(subject.inspect).to eq('#<Faraday::Error response={:status=>400}>') }
|
|
31
|
+
end
|
|
28
32
|
it { expect(subject.response_status).to eq(400) }
|
|
29
33
|
it { expect(subject.response_headers).to be_nil }
|
|
30
34
|
it { expect(subject.response_body).to be_nil }
|
|
@@ -61,7 +65,11 @@ RSpec.describe Faraday::Error do
|
|
|
61
65
|
it { expect(subject.wrapped_exception).to be_nil }
|
|
62
66
|
it { expect(subject.response).to eq(response) }
|
|
63
67
|
it { expect(subject.message).to eq('custom message') }
|
|
64
|
-
|
|
68
|
+
if RUBY_VERSION >= '3.4'
|
|
69
|
+
it { expect(subject.inspect).to eq('#<Faraday::Error response={status: 400}>') }
|
|
70
|
+
else
|
|
71
|
+
it { expect(subject.inspect).to eq('#<Faraday::Error response={:status=>400}>') }
|
|
72
|
+
end
|
|
65
73
|
it { expect(subject.response_status).to eq(400) }
|
|
66
74
|
it { expect(subject.response_headers).to be_nil }
|
|
67
75
|
it { expect(subject.response_body).to be_nil }
|
|
@@ -81,5 +89,87 @@ RSpec.describe Faraday::Error do
|
|
|
81
89
|
it { expect(subject.response_headers).to eq(headers) }
|
|
82
90
|
it { expect(subject.response_body).to eq(body) }
|
|
83
91
|
end
|
|
92
|
+
|
|
93
|
+
context 'with hash missing status key' do
|
|
94
|
+
let(:exception) { { body: 'error body' } }
|
|
95
|
+
|
|
96
|
+
it { expect(subject.wrapped_exception).to be_nil }
|
|
97
|
+
it { expect(subject.response).to eq(exception) }
|
|
98
|
+
it { expect(subject.message).to eq('the server responded with status - method and url are not available due to include_request: false on Faraday::Response::RaiseError middleware') }
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
context 'with hash with status but missing request data' do
|
|
102
|
+
let(:exception) { { status: 404, body: 'not found' } } # missing request key
|
|
103
|
+
|
|
104
|
+
it { expect(subject.wrapped_exception).to be_nil }
|
|
105
|
+
it { expect(subject.response).to eq(exception) }
|
|
106
|
+
it { expect(subject.message).to eq('the server responded with status 404 - method and url are not available due to include_request: false on Faraday::Response::RaiseError middleware') }
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
context 'with hash with status and request but missing method in request' do
|
|
110
|
+
let(:exception) { { status: 404, body: 'not found', request: { url: 'http://example.com/test' } } } # missing method
|
|
111
|
+
|
|
112
|
+
it { expect(subject.wrapped_exception).to be_nil }
|
|
113
|
+
it { expect(subject.response).to eq(exception) }
|
|
114
|
+
it { expect(subject.message).to eq('the server responded with status 404 for http://example.com/test') }
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
context 'with hash with status and request but missing url in request' do
|
|
118
|
+
let(:exception) { { status: 404, body: 'not found', request: { method: :get } } } # missing url
|
|
119
|
+
|
|
120
|
+
it { expect(subject.wrapped_exception).to be_nil }
|
|
121
|
+
it { expect(subject.response).to eq(exception) }
|
|
122
|
+
it { expect(subject.message).to eq('the server responded with status 404 for GET ') }
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
context 'with properly formed Faraday::Env' do
|
|
126
|
+
# This represents the normal case - a well-formed Faraday::Env object
|
|
127
|
+
# with all the standard properties populated as they would be during
|
|
128
|
+
# a typical HTTP request/response cycle
|
|
129
|
+
let(:exception) { Faraday::Env.new }
|
|
130
|
+
|
|
131
|
+
before do
|
|
132
|
+
exception.status = 500
|
|
133
|
+
exception.method = :post
|
|
134
|
+
exception.url = URI('https://api.example.com/users')
|
|
135
|
+
exception.request = Faraday::RequestOptions.new
|
|
136
|
+
exception.response_headers = { 'content-type' => 'application/json' }
|
|
137
|
+
exception.response_body = '{"error": "Internal server error"}'
|
|
138
|
+
exception.request_headers = { 'authorization' => 'Bearer token123' }
|
|
139
|
+
exception.request_body = '{"name": "John"}'
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it { expect(subject.wrapped_exception).to be_nil }
|
|
143
|
+
it { expect(subject.response).to eq(exception) }
|
|
144
|
+
it { expect(subject.message).to eq('the server responded with status 500 for POST https://api.example.com/users') }
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
context 'with Faraday::Env missing status key' do
|
|
148
|
+
let(:exception) { Faraday::Env.new }
|
|
149
|
+
|
|
150
|
+
before do
|
|
151
|
+
exception[:body] = 'error body'
|
|
152
|
+
# Intentionally not setting status
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
it { expect(subject.wrapped_exception).to be_nil }
|
|
156
|
+
it { expect(subject.response).to eq(exception) }
|
|
157
|
+
it { expect(subject.message).to eq('the server responded with status for ') }
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
context 'with Faraday::Env with direct method and url properties' do
|
|
161
|
+
let(:exception) { Faraday::Env.new }
|
|
162
|
+
|
|
163
|
+
before do
|
|
164
|
+
exception.status = 404
|
|
165
|
+
exception.method = :get
|
|
166
|
+
exception.url = URI('http://example.com/test')
|
|
167
|
+
exception[:body] = 'not found'
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it { expect(subject.wrapped_exception).to be_nil }
|
|
171
|
+
it { expect(subject.response).to eq(exception) }
|
|
172
|
+
it { expect(subject.message).to eq('the server responded with status 404 for GET http://example.com/test') }
|
|
173
|
+
end
|
|
84
174
|
end
|
|
85
175
|
end
|
|
@@ -67,4 +67,147 @@ RSpec.describe Faraday::Middleware do
|
|
|
67
67
|
end
|
|
68
68
|
end
|
|
69
69
|
end
|
|
70
|
+
|
|
71
|
+
describe '::default_options' do
|
|
72
|
+
let(:subclass_no_options) { FaradayMiddlewareSubclasses::SubclassNoOptions }
|
|
73
|
+
let(:subclass_one_option) { FaradayMiddlewareSubclasses::SubclassOneOption }
|
|
74
|
+
let(:subclass_two_options) { FaradayMiddlewareSubclasses::SubclassTwoOptions }
|
|
75
|
+
|
|
76
|
+
def build_conn(resp_middleware)
|
|
77
|
+
Faraday.new do |c|
|
|
78
|
+
c.adapter :test do |stub|
|
|
79
|
+
stub.get('/success') { [200, {}, 'ok'] }
|
|
80
|
+
end
|
|
81
|
+
c.response resp_middleware
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
RSpec.shared_context 'reset @default_options' do
|
|
86
|
+
before(:each) do
|
|
87
|
+
FaradayMiddlewareSubclasses::SubclassNoOptions.instance_variable_set(:@default_options, nil)
|
|
88
|
+
FaradayMiddlewareSubclasses::SubclassOneOption.instance_variable_set(:@default_options, nil)
|
|
89
|
+
FaradayMiddlewareSubclasses::SubclassTwoOptions.instance_variable_set(:@default_options, nil)
|
|
90
|
+
Faraday::Middleware.instance_variable_set(:@default_options, nil)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
after(:all) do
|
|
95
|
+
FaradayMiddlewareSubclasses::SubclassNoOptions.instance_variable_set(:@default_options, nil)
|
|
96
|
+
FaradayMiddlewareSubclasses::SubclassOneOption.instance_variable_set(:@default_options, nil)
|
|
97
|
+
FaradayMiddlewareSubclasses::SubclassTwoOptions.instance_variable_set(:@default_options, nil)
|
|
98
|
+
Faraday::Middleware.instance_variable_set(:@default_options, nil)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
context 'with subclass DEFAULT_OPTIONS defined' do
|
|
102
|
+
include_context 'reset @default_options'
|
|
103
|
+
|
|
104
|
+
context 'and without application options configured' do
|
|
105
|
+
let(:resp1) { build_conn(:one_option).get('/success') }
|
|
106
|
+
|
|
107
|
+
it 'has only subclass defaults' do
|
|
108
|
+
expect(Faraday::Middleware.default_options).to eq(Faraday::Middleware::DEFAULT_OPTIONS)
|
|
109
|
+
expect(subclass_no_options.default_options).to eq(subclass_no_options::DEFAULT_OPTIONS)
|
|
110
|
+
expect(subclass_one_option.default_options).to eq(subclass_one_option::DEFAULT_OPTIONS)
|
|
111
|
+
expect(subclass_two_options.default_options).to eq(subclass_two_options::DEFAULT_OPTIONS)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it { expect(resp1.body).to eq('ok') }
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
context "and with one application's options changed" do
|
|
118
|
+
let(:resp2) { build_conn(:two_options).get('/success') }
|
|
119
|
+
|
|
120
|
+
before(:each) do
|
|
121
|
+
FaradayMiddlewareSubclasses::SubclassTwoOptions.default_options = { some_option: false }
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it 'only updates default options of target subclass' do
|
|
125
|
+
expect(Faraday::Middleware.default_options).to eq(Faraday::Middleware::DEFAULT_OPTIONS)
|
|
126
|
+
expect(subclass_no_options.default_options).to eq(subclass_no_options::DEFAULT_OPTIONS)
|
|
127
|
+
expect(subclass_one_option.default_options).to eq(subclass_one_option::DEFAULT_OPTIONS)
|
|
128
|
+
expect(subclass_two_options.default_options).to eq({ some_option: false, some_other_option: false })
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it { expect(resp2.body).to eq('ok') }
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
context "and with two applications' options changed" do
|
|
135
|
+
let(:resp1) { build_conn(:one_option).get('/success') }
|
|
136
|
+
let(:resp2) { build_conn(:two_options).get('/success') }
|
|
137
|
+
|
|
138
|
+
before(:each) do
|
|
139
|
+
FaradayMiddlewareSubclasses::SubclassOneOption.default_options = { some_other_option: true }
|
|
140
|
+
FaradayMiddlewareSubclasses::SubclassTwoOptions.default_options = { some_option: false }
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it 'updates subclasses and parent independent of each other' do
|
|
144
|
+
expect(Faraday::Middleware.default_options).to eq(Faraday::Middleware::DEFAULT_OPTIONS)
|
|
145
|
+
expect(subclass_no_options.default_options).to eq(subclass_no_options::DEFAULT_OPTIONS)
|
|
146
|
+
expect(subclass_one_option.default_options).to eq({ some_other_option: true })
|
|
147
|
+
expect(subclass_two_options.default_options).to eq({ some_option: false, some_other_option: false })
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it { expect(resp1.body).to eq('ok') }
|
|
151
|
+
it { expect(resp2.body).to eq('ok') }
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
context 'with FARADAY::MIDDLEWARE DEFAULT_OPTIONS and with Subclass DEFAULT_OPTIONS' do
|
|
156
|
+
before(:each) do
|
|
157
|
+
stub_const('Faraday::Middleware::DEFAULT_OPTIONS', { its_magic: false })
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Must stub Faraday::Middleware::DEFAULT_OPTIONS before resetting default options
|
|
161
|
+
include_context 'reset @default_options'
|
|
162
|
+
|
|
163
|
+
context 'and without application options configured' do
|
|
164
|
+
let(:resp1) { build_conn(:one_option).get('/success') }
|
|
165
|
+
|
|
166
|
+
it 'has only subclass defaults' do
|
|
167
|
+
expect(Faraday::Middleware.default_options).to eq(Faraday::Middleware::DEFAULT_OPTIONS)
|
|
168
|
+
expect(FaradayMiddlewareSubclasses::SubclassNoOptions.default_options).to eq({ its_magic: false })
|
|
169
|
+
expect(FaradayMiddlewareSubclasses::SubclassOneOption.default_options).to eq({ its_magic: false, some_other_option: false })
|
|
170
|
+
expect(FaradayMiddlewareSubclasses::SubclassTwoOptions.default_options).to eq({ its_magic: false, some_option: true, some_other_option: false })
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
it { expect(resp1.body).to eq('ok') }
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
context "and with two applications' options changed" do
|
|
177
|
+
let(:resp1) { build_conn(:one_option).get('/success') }
|
|
178
|
+
let(:resp2) { build_conn(:two_options).get('/success') }
|
|
179
|
+
|
|
180
|
+
before(:each) do
|
|
181
|
+
FaradayMiddlewareSubclasses::SubclassOneOption.default_options = { some_other_option: true }
|
|
182
|
+
FaradayMiddlewareSubclasses::SubclassTwoOptions.default_options = { some_option: false }
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
it 'updates subclasses and parent independent of each other' do
|
|
186
|
+
expect(Faraday::Middleware.default_options).to eq(Faraday::Middleware::DEFAULT_OPTIONS)
|
|
187
|
+
expect(FaradayMiddlewareSubclasses::SubclassNoOptions.default_options).to eq({ its_magic: false })
|
|
188
|
+
expect(FaradayMiddlewareSubclasses::SubclassOneOption.default_options).to eq({ its_magic: false, some_other_option: true })
|
|
189
|
+
expect(FaradayMiddlewareSubclasses::SubclassTwoOptions.default_options).to eq({ its_magic: false, some_option: false, some_other_option: false })
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
it { expect(resp1.body).to eq('ok') }
|
|
193
|
+
it { expect(resp2.body).to eq('ok') }
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
describe 'default_options input validation' do
|
|
198
|
+
include_context 'reset @default_options'
|
|
199
|
+
|
|
200
|
+
it 'raises error if Faraday::Middleware option does not exist' do
|
|
201
|
+
expect { Faraday::Middleware.default_options = { something_special: true } }.to raise_error(Faraday::InitializationError) do |e|
|
|
202
|
+
expect(e.message).to eq('Invalid options provided. Keys not found in Faraday::Middleware::DEFAULT_OPTIONS: something_special')
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
it 'raises error if subclass option does not exist' do
|
|
207
|
+
expect { subclass_one_option.default_options = { this_is_a_typo: true } }.to raise_error(Faraday::InitializationError) do |e|
|
|
208
|
+
expect(e.message).to eq('Invalid options provided. Keys not found in FaradayMiddlewareSubclasses::SubclassOneOption::DEFAULT_OPTIONS: this_is_a_typo')
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
70
213
|
end
|
|
@@ -27,6 +27,33 @@ RSpec.describe Faraday::ProxyOptions do
|
|
|
27
27
|
expect(options.inspect).to eq('#<Faraday::ProxyOptions (empty)>')
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
it 'works with hash' do
|
|
31
|
+
hash = { user: 'user', password: 'pass', uri: 'http://@example.org' }
|
|
32
|
+
options = Faraday::ProxyOptions.from(hash)
|
|
33
|
+
expect(options.user).to eq('user')
|
|
34
|
+
expect(options.password).to eq('pass')
|
|
35
|
+
expect(options.uri).to be_a_kind_of(URI)
|
|
36
|
+
expect(options.path).to eq('')
|
|
37
|
+
expect(options.port).to eq(80)
|
|
38
|
+
expect(options.host).to eq('example.org')
|
|
39
|
+
expect(options.scheme).to eq('http')
|
|
40
|
+
expect(options.inspect).to match('#<Faraday::ProxyOptions uri=')
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'works with option' do
|
|
44
|
+
opt_arg = { user: 'user', password: 'pass', uri: 'http://@example.org' }
|
|
45
|
+
option = Faraday::ConnectionOptions.from(proxy: opt_arg)
|
|
46
|
+
options = Faraday::ProxyOptions.from(option.proxy)
|
|
47
|
+
expect(options.user).to eq('user')
|
|
48
|
+
expect(options.password).to eq('pass')
|
|
49
|
+
expect(options.uri).to be_a_kind_of(URI)
|
|
50
|
+
expect(options.path).to eq('')
|
|
51
|
+
expect(options.port).to eq(80)
|
|
52
|
+
expect(options.host).to eq('example.org')
|
|
53
|
+
expect(options.scheme).to eq('http')
|
|
54
|
+
expect(options.inspect).to match('#<Faraday::ProxyOptions uri=')
|
|
55
|
+
end
|
|
56
|
+
|
|
30
57
|
it 'works with no auth' do
|
|
31
58
|
proxy = Faraday::ProxyOptions.from 'http://example.org'
|
|
32
59
|
expect(proxy.user).to be_nil
|
|
@@ -62,7 +62,8 @@ RSpec.describe Faraday::NestedParamsEncoder do
|
|
|
62
62
|
it 'encodes rack compat' do
|
|
63
63
|
params = { a: [{ one: '1', two: '2' }, '3', ''] }
|
|
64
64
|
result = Faraday::Utils.unescape(Faraday::NestedParamsEncoder.encode(params)).split('&')
|
|
65
|
-
|
|
65
|
+
escaped = Rack::Utils.build_nested_query(params)
|
|
66
|
+
expected = Rack::Utils.unescape(escaped).split('&')
|
|
66
67
|
expect(result).to match_array(expected)
|
|
67
68
|
end
|
|
68
69
|
|
|
@@ -184,6 +184,23 @@ RSpec.describe Faraday::Response::Json, type: :response do
|
|
|
184
184
|
response = process(body)
|
|
185
185
|
expect(response.body).to eq(result)
|
|
186
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
|
|
187
204
|
end
|
|
188
205
|
end
|
|
189
206
|
end
|
|
@@ -21,6 +21,7 @@ RSpec.describe Faraday::Response::Logger do
|
|
|
21
21
|
stubs.post('/ohai') { [200, { 'Content-Type' => 'text/html' }, 'fred'] }
|
|
22
22
|
stubs.post('/ohyes') { [200, { 'Content-Type' => 'text/html' }, 'pebbles'] }
|
|
23
23
|
stubs.get('/rubbles') { [200, { 'Content-Type' => 'application/json' }, rubbles] }
|
|
24
|
+
stubs.get('/8bit') { [200, { 'Content-Type' => 'text/html' }, (+'café!').force_encoding(Encoding::ASCII_8BIT)] }
|
|
24
25
|
stubs.get('/filtered_body') { [200, { 'Content-Type' => 'text/html' }, 'soylent green is people'] }
|
|
25
26
|
stubs.get('/filtered_headers') { [200, { 'Content-Type' => 'text/html' }, 'headers response'] }
|
|
26
27
|
stubs.get('/filtered_params') { [200, { 'Content-Type' => 'text/html' }, 'params response'] }
|
|
@@ -55,6 +56,26 @@ RSpec.describe Faraday::Response::Logger do
|
|
|
55
56
|
end
|
|
56
57
|
end
|
|
57
58
|
|
|
59
|
+
context 'when logger with program name' do
|
|
60
|
+
let(:logger) { Logger.new(string_io, progname: 'my_best_program') }
|
|
61
|
+
|
|
62
|
+
it 'logs with program name' do
|
|
63
|
+
conn.get '/hello'
|
|
64
|
+
|
|
65
|
+
expect(string_io.string).to match('-- my_best_program: request:')
|
|
66
|
+
expect(string_io.string).to match('-- my_best_program: response:')
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context 'when logger without program name' do
|
|
71
|
+
it 'logs without program name' do
|
|
72
|
+
conn.get '/hello'
|
|
73
|
+
|
|
74
|
+
expect(string_io.string).to match('-- : request:')
|
|
75
|
+
expect(string_io.string).to match('-- : response:')
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
58
79
|
context 'with default formatter' do
|
|
59
80
|
let(:formatter) { instance_double(Faraday::Logging::Formatter, request: true, response: true, filter: []) }
|
|
60
81
|
|
|
@@ -169,7 +190,7 @@ RSpec.describe Faraday::Response::Logger do
|
|
|
169
190
|
context 'when logging request body' do
|
|
170
191
|
let(:logger_options) { { bodies: { request: true } } }
|
|
171
192
|
|
|
172
|
-
it '
|
|
193
|
+
it 'logs only request body' do
|
|
173
194
|
conn.post '/ohyes', 'name=Tamago', accept: 'text/html'
|
|
174
195
|
expect(string_io.string).to match(%(name=Tamago))
|
|
175
196
|
expect(string_io.string).not_to match(%(pebbles))
|
|
@@ -179,7 +200,7 @@ RSpec.describe Faraday::Response::Logger do
|
|
|
179
200
|
context 'when logging response body' do
|
|
180
201
|
let(:logger_options) { { bodies: { response: true } } }
|
|
181
202
|
|
|
182
|
-
it '
|
|
203
|
+
it 'logs only response body' do
|
|
183
204
|
conn.post '/ohyes', 'name=Hamachi', accept: 'text/html'
|
|
184
205
|
expect(string_io.string).to match(%(pebbles))
|
|
185
206
|
expect(string_io.string).not_to match(%(name=Hamachi))
|
|
@@ -189,13 +210,13 @@ RSpec.describe Faraday::Response::Logger do
|
|
|
189
210
|
context 'when logging request and response bodies' do
|
|
190
211
|
let(:logger_options) { { bodies: true } }
|
|
191
212
|
|
|
192
|
-
it '
|
|
213
|
+
it 'logs request and response body' do
|
|
193
214
|
conn.post '/ohyes', 'name=Ebi', accept: 'text/html'
|
|
194
215
|
expect(string_io.string).to match(%(name=Ebi))
|
|
195
216
|
expect(string_io.string).to match(%(pebbles))
|
|
196
217
|
end
|
|
197
218
|
|
|
198
|
-
it '
|
|
219
|
+
it 'logs response body object' do
|
|
199
220
|
conn.get '/rubbles', nil, accept: 'text/html'
|
|
200
221
|
expect(string_io.string).to match(%([\"Barney\", \"Betty\", \"Bam Bam\"]\n))
|
|
201
222
|
end
|
|
@@ -208,6 +229,26 @@ RSpec.describe Faraday::Response::Logger do
|
|
|
208
229
|
end
|
|
209
230
|
end
|
|
210
231
|
|
|
232
|
+
context 'when bodies are logged by default' do
|
|
233
|
+
before do
|
|
234
|
+
described_class.default_options = { bodies: true }
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
it 'logs response body' do
|
|
238
|
+
conn.post '/ohai'
|
|
239
|
+
expect(string_io.string).to match(%(fred))
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
it 'converts to UTF-8' do
|
|
243
|
+
conn.get '/8bit'
|
|
244
|
+
expect(string_io.string).to match(%(caf��!))
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
after do
|
|
248
|
+
described_class.default_options = { bodies: false }
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
211
252
|
context 'when logging errors' do
|
|
212
253
|
let(:logger_options) { { errors: true } }
|
|
213
254
|
|