faraday 1.0.0 → 1.3.1
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 +104 -0
- data/LICENSE.md +1 -1
- data/README.md +4 -5
- data/examples/client_spec.rb +1 -1
- data/lib/faraday.rb +51 -41
- data/lib/faraday/adapter.rb +1 -1
- data/lib/faraday/adapter/em_http.rb +18 -14
- data/lib/faraday/adapter/em_synchrony.rb +16 -13
- data/lib/faraday/adapter/excon.rb +2 -2
- data/lib/faraday/adapter/httpclient.rb +2 -1
- data/lib/faraday/adapter/net_http_persistent.rb +1 -1
- data/lib/faraday/adapter/typhoeus.rb +1 -1
- data/lib/faraday/adapter_registry.rb +3 -1
- data/lib/faraday/autoload.rb +1 -2
- data/lib/faraday/connection.rb +5 -4
- data/lib/faraday/encoders/flat_params_encoder.rb +9 -2
- data/lib/faraday/encoders/nested_params_encoder.rb +7 -2
- data/lib/faraday/error.rb +20 -0
- data/lib/faraday/methods.rb +6 -0
- data/lib/faraday/middleware.rb +14 -4
- data/lib/faraday/options.rb +4 -8
- data/lib/faraday/rack_builder.rb +13 -12
- data/lib/faraday/request.rb +20 -10
- data/lib/faraday/request/authorization.rb +3 -1
- data/lib/faraday/request/multipart.rb +10 -3
- data/lib/faraday/request/retry.rb +2 -2
- data/lib/faraday/request/url_encoded.rb +3 -1
- data/lib/faraday/response.rb +4 -7
- data/lib/faraday/response/raise_error.rb +12 -1
- data/lib/faraday/utils.rb +11 -3
- data/lib/faraday/utils/headers.rb +2 -2
- data/lib/faraday/version.rb +5 -0
- data/spec/faraday/adapter/em_http_spec.rb +1 -1
- data/spec/faraday/adapter/em_synchrony_spec.rb +1 -1
- data/spec/faraday/adapter/patron_spec.rb +1 -1
- data/spec/faraday/adapter/test_spec.rb +260 -0
- data/spec/faraday/connection_spec.rb +30 -0
- data/spec/faraday/error_spec.rb +15 -0
- data/spec/faraday/middleware_spec.rb +32 -6
- data/spec/faraday/params_encoders/flat_spec.rb +8 -0
- data/spec/faraday/params_encoders/nested_spec.rb +8 -0
- data/spec/faraday/rack_builder_spec.rb +150 -1
- data/spec/faraday/request/authorization_spec.rb +2 -2
- data/spec/faraday/request/multipart_spec.rb +41 -13
- data/spec/faraday/request/retry_spec.rb +1 -1
- data/spec/faraday/request/url_encoded_spec.rb +13 -0
- data/spec/faraday/request_spec.rb +16 -5
- data/spec/faraday/response/middleware_spec.rb +16 -0
- data/spec/faraday/response/raise_error_spec.rb +63 -0
- data/spec/support/shared_examples/adapter.rb +2 -1
- data/spec/support/shared_examples/request_method.rb +39 -11
- metadata +37 -7
- data/UPGRADING.md +0 -55
- data/lib/faraday/adapter/net_http.rb +0 -209
@@ -2,23 +2,49 @@
|
|
2
2
|
|
3
3
|
RSpec.describe Faraday::Middleware do
|
4
4
|
subject { described_class.new(app) }
|
5
|
+
let(:app) { double }
|
6
|
+
|
7
|
+
describe 'options' do
|
8
|
+
context 'when options are passed to the middleware' do
|
9
|
+
subject { described_class.new(app, options) }
|
10
|
+
let(:options) { { field: 'value' } }
|
11
|
+
|
12
|
+
it 'accepts options when initialized' do
|
13
|
+
expect(subject.options[:field]).to eq('value')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#on_request' do
|
19
|
+
subject do
|
20
|
+
Class.new(described_class) do
|
21
|
+
def on_request(env)
|
22
|
+
# do nothing
|
23
|
+
end
|
24
|
+
end.new(app)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'is called by #call' do
|
28
|
+
expect(app).to receive(:call).and_return(app)
|
29
|
+
expect(app).to receive(:on_complete)
|
30
|
+
is_expected.to receive(:call).and_call_original
|
31
|
+
is_expected.to receive(:on_request)
|
32
|
+
subject.call(double)
|
33
|
+
end
|
34
|
+
end
|
5
35
|
|
6
36
|
describe '#close' do
|
7
37
|
context "with app that doesn't support \#close" do
|
8
|
-
let(:app) { double }
|
9
|
-
|
10
38
|
it 'should issue warning' do
|
11
|
-
|
39
|
+
is_expected.to receive(:warn)
|
12
40
|
subject.close
|
13
41
|
end
|
14
42
|
end
|
15
43
|
|
16
44
|
context "with app that supports \#close" do
|
17
|
-
let(:app) { double }
|
18
|
-
|
19
45
|
it 'should issue warning' do
|
20
46
|
expect(app).to receive(:close)
|
21
|
-
|
47
|
+
is_expected.to_not receive(:warn)
|
22
48
|
subject.close
|
23
49
|
end
|
24
50
|
end
|
@@ -31,4 +31,12 @@ RSpec.describe Faraday::FlatParamsEncoder do
|
|
31
31
|
params = { a: [] }
|
32
32
|
expect(subject.encode(params)).to eq('a=')
|
33
33
|
end
|
34
|
+
|
35
|
+
it 'encodes unsorted when asked' do
|
36
|
+
params = { b: false, a: true }
|
37
|
+
expect(subject.encode(params)).to eq('a=true&b=false')
|
38
|
+
Faraday::FlatParamsEncoder.sort_params = false
|
39
|
+
expect(subject.encode(params)).to eq('b=false&a=true')
|
40
|
+
Faraday::FlatParamsEncoder.sort_params = true
|
41
|
+
end
|
34
42
|
end
|
@@ -94,6 +94,14 @@ RSpec.describe Faraday::NestedParamsEncoder do
|
|
94
94
|
expect(subject.encode(params)).to eq('a%5B%5D=true&a%5B%5D=false')
|
95
95
|
end
|
96
96
|
|
97
|
+
it 'encodes unsorted when asked' do
|
98
|
+
params = { b: false, a: true }
|
99
|
+
expect(subject.encode(params)).to eq('a=true&b=false')
|
100
|
+
Faraday::NestedParamsEncoder.sort_params = false
|
101
|
+
expect(subject.encode(params)).to eq('b=false&a=true')
|
102
|
+
Faraday::NestedParamsEncoder.sort_params = true
|
103
|
+
end
|
104
|
+
|
97
105
|
shared_examples 'a wrong decoding' do
|
98
106
|
it do
|
99
107
|
expect { subject.decode(query) }.to raise_error(TypeError) do |e|
|
@@ -189,8 +189,157 @@ RSpec.describe Faraday::RackBuilder do
|
|
189
189
|
|
190
190
|
it 'raises an error while making a request' do
|
191
191
|
expect { conn.get('/') }.to raise_error(RuntimeError) do |err|
|
192
|
-
expect(err.message).to
|
192
|
+
expect(err.message).to match(%r{missing dependency for Broken: .+ -- zomg/i_dont/exist})
|
193
193
|
end
|
194
194
|
end
|
195
195
|
end
|
196
|
+
|
197
|
+
context 'when middleware is added with named arguments' do
|
198
|
+
let(:conn) { Faraday::Connection.new {} }
|
199
|
+
|
200
|
+
let(:dog_middleware) do
|
201
|
+
Class.new(Faraday::Middleware) do
|
202
|
+
attr_accessor :name
|
203
|
+
|
204
|
+
def initialize(app, name:)
|
205
|
+
super(app)
|
206
|
+
@name = name
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
let(:dog) do
|
211
|
+
subject.handlers.find { |handler| handler == dog_middleware }.build
|
212
|
+
end
|
213
|
+
|
214
|
+
it 'adds a handler to construct middleware with options passed to use' do
|
215
|
+
subject.use dog_middleware, name: 'Rex'
|
216
|
+
expect { dog }.to_not output(
|
217
|
+
/warning: Using the last argument as keyword parameters is deprecated/
|
218
|
+
).to_stderr
|
219
|
+
expect(dog.name).to eq('Rex')
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
context 'when a request adapter is added with named arguments' do
|
224
|
+
let(:conn) { Faraday::Connection.new {} }
|
225
|
+
|
226
|
+
let(:cat_request) do
|
227
|
+
Class.new(Faraday::Middleware) do
|
228
|
+
attr_accessor :name
|
229
|
+
|
230
|
+
def initialize(app, name:)
|
231
|
+
super(app)
|
232
|
+
@name = name
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
let(:cat) do
|
237
|
+
subject.handlers.find { |handler| handler == cat_request }.build
|
238
|
+
end
|
239
|
+
|
240
|
+
it 'adds a handler to construct request adapter with options passed to request' do
|
241
|
+
Faraday::Request.register_middleware cat_request: cat_request
|
242
|
+
subject.request :cat_request, name: 'Felix'
|
243
|
+
expect { cat }.to_not output(
|
244
|
+
/warning: Using the last argument as keyword parameters is deprecated/
|
245
|
+
).to_stderr
|
246
|
+
expect(cat.name).to eq('Felix')
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
context 'when a response adapter is added with named arguments' do
|
251
|
+
let(:conn) { Faraday::Connection.new {} }
|
252
|
+
|
253
|
+
let(:fish_response) do
|
254
|
+
Class.new(Faraday::Response::Middleware) do
|
255
|
+
attr_accessor :name
|
256
|
+
|
257
|
+
def initialize(app, name:)
|
258
|
+
super(app)
|
259
|
+
@name = name
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
let(:fish) do
|
264
|
+
subject.handlers.find { |handler| handler == fish_response }.build
|
265
|
+
end
|
266
|
+
|
267
|
+
it 'adds a handler to construct response adapter with options passed to response' do
|
268
|
+
Faraday::Response.register_middleware fish_response: fish_response
|
269
|
+
subject.response :fish_response, name: 'Bubbles'
|
270
|
+
expect { fish }.to_not output(
|
271
|
+
/warning: Using the last argument as keyword parameters is deprecated/
|
272
|
+
).to_stderr
|
273
|
+
expect(fish.name).to eq('Bubbles')
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
context 'when a plain adapter is added with named arguments' do
|
278
|
+
let(:conn) { Faraday::Connection.new {} }
|
279
|
+
|
280
|
+
let(:rabbit_adapter) do
|
281
|
+
Class.new(Faraday::Adapter) do
|
282
|
+
attr_accessor :name
|
283
|
+
|
284
|
+
def initialize(app, name:)
|
285
|
+
super(app)
|
286
|
+
@name = name
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
let(:rabbit) do
|
291
|
+
subject.adapter.build
|
292
|
+
end
|
293
|
+
|
294
|
+
it 'adds a handler to construct adapter with options passed to adapter' do
|
295
|
+
Faraday::Adapter.register_middleware rabbit_adapter: rabbit_adapter
|
296
|
+
subject.adapter :rabbit_adapter, name: 'Thumper'
|
297
|
+
expect { rabbit }.to_not output(
|
298
|
+
/warning: Using the last argument as keyword parameters is deprecated/
|
299
|
+
).to_stderr
|
300
|
+
expect(rabbit.name).to eq('Thumper')
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
context 'when handlers are directly added or updated' do
|
305
|
+
let(:conn) { Faraday::Connection.new {} }
|
306
|
+
|
307
|
+
let(:rock_handler) do
|
308
|
+
Class.new do
|
309
|
+
attr_accessor :name
|
310
|
+
|
311
|
+
def initialize(_app, name:)
|
312
|
+
@name = name
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
let(:rock) do
|
317
|
+
subject.handlers.find { |handler| handler == rock_handler }.build
|
318
|
+
end
|
319
|
+
|
320
|
+
it 'adds a handler to construct adapter with options passed to insert' do
|
321
|
+
subject.insert 0, rock_handler, name: 'Stony'
|
322
|
+
expect { rock }.to_not output(
|
323
|
+
/warning: Using the last argument as keyword parameters is deprecated/
|
324
|
+
).to_stderr
|
325
|
+
expect(rock.name).to eq('Stony')
|
326
|
+
end
|
327
|
+
|
328
|
+
it 'adds a handler with options passed to insert_after' do
|
329
|
+
subject.insert_after 0, rock_handler, name: 'Rocky'
|
330
|
+
expect { rock }.to_not output(
|
331
|
+
/warning: Using the last argument as keyword parameters is deprecated/
|
332
|
+
).to_stderr
|
333
|
+
expect(rock.name).to eq('Rocky')
|
334
|
+
end
|
335
|
+
|
336
|
+
it 'adds a handler with options passed to swap' do
|
337
|
+
subject.insert 0, rock_handler, name: 'Flint'
|
338
|
+
subject.swap 0, rock_handler, name: 'Chert'
|
339
|
+
expect { rock }.to_not output(
|
340
|
+
/warning: Using the last argument as keyword parameters is deprecated/
|
341
|
+
).to_stderr
|
342
|
+
expect(rock.name).to eq('Chert')
|
343
|
+
end
|
344
|
+
end
|
196
345
|
end
|
@@ -56,7 +56,7 @@ RSpec.describe Faraday::Request::Authorization do
|
|
56
56
|
end
|
57
57
|
|
58
58
|
context 'when other values are provided' do
|
59
|
-
let(:auth_config) { ['baz', foo: 42] }
|
59
|
+
let(:auth_config) { ['baz', { foo: 42 }] }
|
60
60
|
|
61
61
|
it { expect(response.body).to match(/^Token /) }
|
62
62
|
it { expect(response.body).to match(/token="baz"/) }
|
@@ -78,7 +78,7 @@ RSpec.describe Faraday::Request::Authorization do
|
|
78
78
|
end
|
79
79
|
|
80
80
|
context 'when passed a string and a hash' do
|
81
|
-
let(:auth_config) { ['baz', foo: 42] }
|
81
|
+
let(:auth_config) { ['baz', { foo: 42 }] }
|
82
82
|
|
83
83
|
it { expect(response.body).to eq('baz foo="42"') }
|
84
84
|
|
@@ -1,9 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
RSpec.describe Faraday::Request::Multipart do
|
4
|
+
let(:options) { {} }
|
4
5
|
let(:conn) do
|
5
6
|
Faraday.new do |b|
|
6
|
-
b.request :multipart
|
7
|
+
b.request :multipart, options
|
7
8
|
b.request :url_encoded
|
8
9
|
b.adapter :test do |stub|
|
9
10
|
stub.post('/echo') do |env|
|
@@ -54,9 +55,10 @@ RSpec.describe Faraday::Request::Multipart do
|
|
54
55
|
part_bc, body_bc = result.part('b[c]')
|
55
56
|
expect(part_bc).to_not be_nil
|
56
57
|
expect(part_bc.filename).to eq('multipart_spec.rb')
|
57
|
-
expect(part_bc.headers['content-disposition'])
|
58
|
-
|
59
|
-
|
58
|
+
expect(part_bc.headers['content-disposition'])
|
59
|
+
.to eq(
|
60
|
+
'form-data; foo=1; name="b[c]"; filename="multipart_spec.rb"'
|
61
|
+
)
|
60
62
|
expect(part_bc.headers['content-type']).to eq('text/x-ruby')
|
61
63
|
expect(part_bc.headers['content-transfer-encoding']).to eq('binary')
|
62
64
|
expect(body_bc).to eq(File.read(__FILE__))
|
@@ -135,9 +137,10 @@ RSpec.describe Faraday::Request::Multipart do
|
|
135
137
|
part_bc, body_bc = result.part('b[][c]')
|
136
138
|
expect(part_bc).to_not be_nil
|
137
139
|
expect(part_bc.filename).to eq('multipart_spec.rb')
|
138
|
-
expect(part_bc.headers['content-disposition'])
|
139
|
-
|
140
|
-
|
140
|
+
expect(part_bc.headers['content-disposition'])
|
141
|
+
.to eq(
|
142
|
+
'form-data; name="b[][c]"; filename="multipart_spec.rb"'
|
143
|
+
)
|
141
144
|
expect(part_bc.headers['content-type']).to eq('text/x-ruby')
|
142
145
|
expect(part_bc.headers['content-transfer-encoding']).to eq('binary')
|
143
146
|
expect(body_bc).to eq(File.read(__FILE__))
|
@@ -177,9 +180,10 @@ RSpec.describe Faraday::Request::Multipart do
|
|
177
180
|
part_bc, body_bc = result.part('b[c]')
|
178
181
|
expect(part_bc).to_not be_nil
|
179
182
|
expect(part_bc.filename).to eq('multipart_spec.rb')
|
180
|
-
expect(part_bc.headers['content-disposition'])
|
181
|
-
|
182
|
-
|
183
|
+
expect(part_bc.headers['content-disposition'])
|
184
|
+
.to eq(
|
185
|
+
'form-data; foo=1; name="b[c]"; filename="multipart_spec.rb"'
|
186
|
+
)
|
183
187
|
expect(part_bc.headers['content-type']).to eq('text/x-ruby')
|
184
188
|
expect(part_bc.headers['content-transfer-encoding']).to eq('binary')
|
185
189
|
expect(body_bc).to eq(File.read(__FILE__))
|
@@ -258,9 +262,10 @@ RSpec.describe Faraday::Request::Multipart do
|
|
258
262
|
part_bc, body_bc = result.part('b[][c]')
|
259
263
|
expect(part_bc).to_not be_nil
|
260
264
|
expect(part_bc.filename).to eq('multipart_spec.rb')
|
261
|
-
expect(part_bc.headers['content-disposition'])
|
262
|
-
|
263
|
-
|
265
|
+
expect(part_bc.headers['content-disposition'])
|
266
|
+
.to eq(
|
267
|
+
'form-data; name="b[][c]"; filename="multipart_spec.rb"'
|
268
|
+
)
|
264
269
|
expect(part_bc.headers['content-type']).to eq('text/x-ruby')
|
265
270
|
expect(part_bc.headers['content-transfer-encoding']).to eq('binary')
|
266
271
|
expect(body_bc).to eq(File.read(__FILE__))
|
@@ -271,4 +276,27 @@ RSpec.describe Faraday::Request::Multipart do
|
|
271
276
|
expect(body_bd).to eq('2')
|
272
277
|
end
|
273
278
|
end
|
279
|
+
|
280
|
+
context 'when passing flat_encode=true option' do
|
281
|
+
let(:options) { { flat_encode: true } }
|
282
|
+
let(:io) { StringIO.new('io-content') }
|
283
|
+
let(:payload) do
|
284
|
+
{
|
285
|
+
a: 1,
|
286
|
+
b: [
|
287
|
+
Faraday::UploadIO.new(io, 'application/pdf'),
|
288
|
+
Faraday::UploadIO.new(io, 'application/pdf')
|
289
|
+
]
|
290
|
+
}
|
291
|
+
end
|
292
|
+
|
293
|
+
it_behaves_like 'a multipart request'
|
294
|
+
|
295
|
+
it 'encode params using flat encoder' do
|
296
|
+
response = conn.post('/echo', payload)
|
297
|
+
|
298
|
+
expect(response.body).to include('name="b"')
|
299
|
+
expect(response.body).not_to include('name="b[]"')
|
300
|
+
end
|
301
|
+
end
|
274
302
|
end
|
@@ -117,7 +117,7 @@ RSpec.describe Faraday::Request::Retry do
|
|
117
117
|
let(:options) { { max: 2, interval: 0.1, interval_randomness: 0.05 } }
|
118
118
|
let(:middleware) { Faraday::Request::Retry.new(nil, options) }
|
119
119
|
|
120
|
-
it { expect(middleware.send(:calculate_retry_interval, 2)).to be_between(0.1, 0.
|
120
|
+
it { expect(middleware.send(:calculate_retry_interval, 2)).to be_between(0.1, 0.105) }
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
@@ -67,4 +67,17 @@ RSpec.describe Faraday::Request::UrlEncoded do
|
|
67
67
|
response = conn.post('/echo', 'a' => { 'b' => { 'c' => ['d'] } })
|
68
68
|
expect(response.body).to eq('a%5Bb%5D%5Bc%5D%5B%5D=d')
|
69
69
|
end
|
70
|
+
|
71
|
+
context 'customising default_space_encoding' do
|
72
|
+
around do |example|
|
73
|
+
Faraday::Utils.default_space_encoding = '%20'
|
74
|
+
example.run
|
75
|
+
Faraday::Utils.default_space_encoding = nil
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'uses the custom character to encode spaces' do
|
79
|
+
response = conn.post('/echo', str: 'apple banana')
|
80
|
+
expect(response.body).to eq('str=apple%20banana')
|
81
|
+
end
|
82
|
+
end
|
70
83
|
end
|
@@ -6,20 +6,31 @@ RSpec.describe Faraday::Request do
|
|
6
6
|
headers: { 'Mime-Version' => '1.0' },
|
7
7
|
request: { oauth: { consumer_key: 'anonymous' } })
|
8
8
|
end
|
9
|
-
let(:
|
9
|
+
let(:http_method) { :get }
|
10
10
|
let(:block) { nil }
|
11
11
|
|
12
|
-
subject { conn.build_request(
|
12
|
+
subject { conn.build_request(http_method, &block) }
|
13
13
|
|
14
14
|
context 'when nothing particular is configured' do
|
15
|
-
it { expect(subject.
|
15
|
+
it { expect(subject.http_method).to eq(:get) }
|
16
16
|
it { expect(subject.to_env(conn).ssl.verify).to be_falsey }
|
17
17
|
end
|
18
18
|
|
19
|
-
context 'when method is post' do
|
20
|
-
let(:
|
19
|
+
context 'when HTTP method is post' do
|
20
|
+
let(:http_method) { :post }
|
21
|
+
|
22
|
+
it { expect(subject.http_method).to eq(:post) }
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'deprecate method for HTTP method' do
|
26
|
+
let(:http_method) { :post }
|
27
|
+
let(:expected_warning) do
|
28
|
+
%r{WARNING: `Faraday::Request#method` is deprecated; use `#http_method` instead. It will be removed in or after version 2.0.\n`Faraday::Request#method` called from .+/spec/faraday/request_spec.rb:\d+.}
|
29
|
+
end
|
21
30
|
|
22
31
|
it { expect(subject.method).to eq(:post) }
|
32
|
+
|
33
|
+
it { expect { subject.method }.to output(expected_warning).to_stderr }
|
23
34
|
end
|
24
35
|
|
25
36
|
context 'when setting the url on setup with a URI' do
|
@@ -26,6 +26,22 @@ RSpec.describe Faraday::Response::Middleware do
|
|
26
26
|
end
|
27
27
|
end
|
28
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
|
+
|
29
45
|
context 'with a custom ResponseMiddleware but empty response' do
|
30
46
|
let(:custom_middleware) do
|
31
47
|
Class.new(Faraday::Response::Middleware) do
|