faraday 0.17.3 → 1.0.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 +52 -8
- data/LICENSE.md +1 -1
- data/README.md +18 -358
- data/Rakefile +1 -7
- data/examples/client_spec.rb +65 -0
- data/examples/client_test.rb +79 -0
- data/lib/faraday.rb +94 -175
- data/lib/faraday/adapter.rb +82 -22
- data/lib/faraday/adapter/em_http.rb +142 -99
- 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 +50 -27
- 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 +37 -0
- data/lib/faraday/encoders/flat_params_encoder.rb +98 -0
- data/lib/faraday/encoders/nested_params_encoder.rb +171 -0
- data/lib/faraday/error.rb +9 -35
- 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 +32 -183
- 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 +66 -55
- data/lib/faraday/request.rb +68 -36
- 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 +79 -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 +38 -18
- data/lib/faraday/utils.rb +36 -245
- 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/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 +34 -0
- data/spec/faraday/params_encoders/nested_spec.rb +134 -0
- data/spec/faraday/rack_builder_spec.rb +196 -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 +274 -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 +109 -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 +15 -15
- 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 -36
- 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 +66 -38
- data/lib/faraday/deprecate.rb +0 -107
- 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,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Faraday::Request::UrlEncoded do
|
4
|
+
let(:conn) do
|
5
|
+
Faraday.new do |b|
|
6
|
+
b.request :multipart
|
7
|
+
b.request :url_encoded
|
8
|
+
b.adapter :test do |stub|
|
9
|
+
stub.post('/echo') do |env|
|
10
|
+
posted_as = env[:request_headers]['Content-Type']
|
11
|
+
[200, { 'Content-Type' => posted_as }, env[:body]]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'does nothing without payload' do
|
18
|
+
response = conn.post('/echo')
|
19
|
+
expect(response.headers['Content-Type']).to be_nil
|
20
|
+
expect(response.body.empty?).to be_truthy
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'ignores custom content type' do
|
24
|
+
response = conn.post('/echo', { some: 'data' }, 'content-type' => 'application/x-foo')
|
25
|
+
expect(response.headers['Content-Type']).to eq('application/x-foo')
|
26
|
+
expect(response.body).to eq(some: 'data')
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'works with no headers' do
|
30
|
+
response = conn.post('/echo', fruit: %w[apples oranges])
|
31
|
+
expect(response.headers['Content-Type']).to eq('application/x-www-form-urlencoded')
|
32
|
+
expect(response.body).to eq('fruit%5B%5D=apples&fruit%5B%5D=oranges')
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'works with with headers' do
|
36
|
+
response = conn.post('/echo', { 'a' => 123 }, 'content-type' => 'application/x-www-form-urlencoded')
|
37
|
+
expect(response.headers['Content-Type']).to eq('application/x-www-form-urlencoded')
|
38
|
+
expect(response.body).to eq('a=123')
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'works with nested params' do
|
42
|
+
response = conn.post('/echo', user: { name: 'Mislav', web: 'mislav.net' })
|
43
|
+
expect(response.headers['Content-Type']).to eq('application/x-www-form-urlencoded')
|
44
|
+
expected = { 'user' => { 'name' => 'Mislav', 'web' => 'mislav.net' } }
|
45
|
+
expect(Faraday::Utils.parse_nested_query(response.body)).to eq(expected)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'works with non nested params' do
|
49
|
+
response = conn.post('/echo', dimensions: %w[date location]) do |req|
|
50
|
+
req.options.params_encoder = Faraday::FlatParamsEncoder
|
51
|
+
end
|
52
|
+
expect(response.headers['Content-Type']).to eq('application/x-www-form-urlencoded')
|
53
|
+
expected = { 'dimensions' => %w[date location] }
|
54
|
+
expect(Faraday::Utils.parse_query(response.body)).to eq(expected)
|
55
|
+
expect(response.body).to eq('dimensions=date&dimensions=location')
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'works with unicode' do
|
59
|
+
err = capture_warnings do
|
60
|
+
response = conn.post('/echo', str: 'eé cç aã aâ')
|
61
|
+
expect(response.body).to eq('str=e%C3%A9+c%C3%A7+a%C3%A3+a%C3%A2')
|
62
|
+
end
|
63
|
+
expect(err.empty?).to be_truthy
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'works with nested keys' do
|
67
|
+
response = conn.post('/echo', 'a' => { 'b' => { 'c' => ['d'] } })
|
68
|
+
expect(response.body).to eq('a%5Bb%5D%5Bc%5D%5B%5D=d')
|
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
|
83
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Faraday::Request do
|
4
|
+
let(:conn) do
|
5
|
+
Faraday.new(url: 'http://sushi.com/api',
|
6
|
+
headers: { 'Mime-Version' => '1.0' },
|
7
|
+
request: { oauth: { consumer_key: 'anonymous' } })
|
8
|
+
end
|
9
|
+
let(:method) { :get }
|
10
|
+
let(:block) { nil }
|
11
|
+
|
12
|
+
subject { conn.build_request(method, &block) }
|
13
|
+
|
14
|
+
context 'when nothing particular is configured' do
|
15
|
+
it { expect(subject.method).to eq(:get) }
|
16
|
+
it { expect(subject.to_env(conn).ssl.verify).to be_falsey }
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'when method is post' do
|
20
|
+
let(:method) { :post }
|
21
|
+
|
22
|
+
it { expect(subject.method).to eq(:post) }
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when setting the url on setup with a URI' do
|
26
|
+
let(:block) { proc { |req| req.url URI.parse('foo.json?a=1') } }
|
27
|
+
|
28
|
+
it { expect(subject.path).to eq(URI.parse('foo.json')) }
|
29
|
+
it { expect(subject.params).to eq('a' => '1') }
|
30
|
+
it { expect(subject.to_env(conn).url.to_s).to eq('http://sushi.com/api/foo.json?a=1') }
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'when setting the url on setup with a string path and params' do
|
34
|
+
let(:block) { proc { |req| req.url 'foo.json', 'a' => 1 } }
|
35
|
+
|
36
|
+
it { expect(subject.path).to eq('foo.json') }
|
37
|
+
it { expect(subject.params).to eq('a' => 1) }
|
38
|
+
it { expect(subject.to_env(conn).url.to_s).to eq('http://sushi.com/api/foo.json?a=1') }
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'when setting the url on setup with a path including params' do
|
42
|
+
let(:block) { proc { |req| req.url 'foo.json?b=2&a=1#qqq' } }
|
43
|
+
|
44
|
+
it { expect(subject.path).to eq('foo.json') }
|
45
|
+
it { expect(subject.params).to eq('a' => '1', 'b' => '2') }
|
46
|
+
it { expect(subject.to_env(conn).url.to_s).to eq('http://sushi.com/api/foo.json?a=1&b=2') }
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'when setting a header on setup with []= syntax' do
|
50
|
+
let(:block) { proc { |req| req['Server'] = 'Faraday' } }
|
51
|
+
let(:headers) { subject.to_env(conn).request_headers }
|
52
|
+
|
53
|
+
it { expect(subject.headers['Server']).to eq('Faraday') }
|
54
|
+
it { expect(headers['mime-version']).to eq('1.0') }
|
55
|
+
it { expect(headers['server']).to eq('Faraday') }
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'when setting the body on setup' do
|
59
|
+
let(:block) { proc { |req| req.body = 'hi' } }
|
60
|
+
|
61
|
+
it { expect(subject.body).to eq('hi') }
|
62
|
+
it { expect(subject.to_env(conn).body).to eq('hi') }
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'with global request options set' do
|
66
|
+
let(:env_request) { subject.to_env(conn).request }
|
67
|
+
|
68
|
+
before do
|
69
|
+
conn.options.timeout = 3
|
70
|
+
conn.options.open_timeout = 5
|
71
|
+
conn.ssl.verify = false
|
72
|
+
conn.proxy = 'http://proxy.com'
|
73
|
+
end
|
74
|
+
|
75
|
+
it { expect(subject.options.timeout).to eq(3) }
|
76
|
+
it { expect(subject.options.open_timeout).to eq(5) }
|
77
|
+
it { expect(env_request.timeout).to eq(3) }
|
78
|
+
it { expect(env_request.open_timeout).to eq(5) }
|
79
|
+
|
80
|
+
context 'and per-request options set' do
|
81
|
+
let(:block) do
|
82
|
+
proc do |req|
|
83
|
+
req.options.timeout = 10
|
84
|
+
req.options.boundary = 'boo'
|
85
|
+
req.options.oauth[:consumer_secret] = 'xyz'
|
86
|
+
req.options.context = {
|
87
|
+
foo: 'foo',
|
88
|
+
bar: 'bar'
|
89
|
+
}
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it { expect(subject.options.timeout).to eq(10) }
|
94
|
+
it { expect(subject.options.open_timeout).to eq(5) }
|
95
|
+
it { expect(env_request.timeout).to eq(10) }
|
96
|
+
it { expect(env_request.open_timeout).to eq(5) }
|
97
|
+
it { expect(env_request.boundary).to eq('boo') }
|
98
|
+
it { expect(env_request.context).to eq(foo: 'foo', bar: 'bar') }
|
99
|
+
it do
|
100
|
+
oauth_expected = { consumer_secret: 'xyz', consumer_key: 'anonymous' }
|
101
|
+
expect(env_request.oauth).to eq(oauth_expected)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'supports marshal serialization' do
|
107
|
+
expect(Marshal.load(Marshal.dump(subject))).to eq(subject)
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,220 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'stringio'
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
RSpec.describe Faraday::Response::Logger do
|
7
|
+
let(:string_io) { StringIO.new }
|
8
|
+
let(:logger) { Logger.new(string_io) }
|
9
|
+
let(:logger_options) { {} }
|
10
|
+
let(:conn) do
|
11
|
+
rubbles = ['Barney', 'Betty', 'Bam Bam']
|
12
|
+
|
13
|
+
Faraday.new do |b|
|
14
|
+
b.response :logger, logger, logger_options do |logger|
|
15
|
+
logger.filter(/(soylent green is) (.+)/, '\1 tasty')
|
16
|
+
logger.filter(/(api_key:).*"(.+)."/, '\1[API_KEY]')
|
17
|
+
logger.filter(/(password)=(.+)/, '\1=[HIDDEN]')
|
18
|
+
end
|
19
|
+
b.adapter :test do |stubs|
|
20
|
+
stubs.get('/hello') { [200, { 'Content-Type' => 'text/html' }, 'hello'] }
|
21
|
+
stubs.post('/ohai') { [200, { 'Content-Type' => 'text/html' }, 'fred'] }
|
22
|
+
stubs.post('/ohyes') { [200, { 'Content-Type' => 'text/html' }, 'pebbles'] }
|
23
|
+
stubs.get('/rubbles') { [200, { 'Content-Type' => 'application/json' }, rubbles] }
|
24
|
+
stubs.get('/filtered_body') { [200, { 'Content-Type' => 'text/html' }, 'soylent green is people'] }
|
25
|
+
stubs.get('/filtered_headers') { [200, { 'Content-Type' => 'text/html' }, 'headers response'] }
|
26
|
+
stubs.get('/filtered_params') { [200, { 'Content-Type' => 'text/html' }, 'params response'] }
|
27
|
+
stubs.get('/filtered_url') { [200, { 'Content-Type' => 'text/html' }, 'url response'] }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
before do
|
33
|
+
logger.level = Logger::DEBUG
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'still returns output' do
|
37
|
+
resp = conn.get '/hello', nil, accept: 'text/html'
|
38
|
+
expect(resp.body).to eq('hello')
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'without configuration' do
|
42
|
+
let(:conn) do
|
43
|
+
Faraday.new do |b|
|
44
|
+
b.response :logger
|
45
|
+
b.adapter :test do |stubs|
|
46
|
+
stubs.get('/hello') { [200, { 'Content-Type' => 'text/html' }, 'hello'] }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'defaults to stdout' do
|
52
|
+
expect(Logger).to receive(:new).with($stdout).and_return(Logger.new(nil))
|
53
|
+
conn.get('/hello')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'with default formatter' do
|
58
|
+
let(:formatter) { instance_double(Faraday::Logging::Formatter, request: true, response: true, filter: []) }
|
59
|
+
|
60
|
+
before { allow(Faraday::Logging::Formatter).to receive(:new).and_return(formatter) }
|
61
|
+
|
62
|
+
it 'delegates logging to the formatter' do
|
63
|
+
expect(formatter).to receive(:request).with(an_instance_of(Faraday::Env))
|
64
|
+
expect(formatter).to receive(:response).with(an_instance_of(Faraday::Env))
|
65
|
+
conn.get '/hello'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'with custom formatter' do
|
70
|
+
let(:formatter_class) do
|
71
|
+
Class.new(Faraday::Logging::Formatter) do
|
72
|
+
def request(_env)
|
73
|
+
info 'Custom log formatter request'
|
74
|
+
end
|
75
|
+
|
76
|
+
def response(_env)
|
77
|
+
info 'Custom log formatter response'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
let(:logger_options) { { formatter: formatter_class } }
|
83
|
+
|
84
|
+
it 'logs with custom formatter' do
|
85
|
+
conn.get '/hello'
|
86
|
+
|
87
|
+
expect(string_io.string).to match('Custom log formatter request')
|
88
|
+
expect(string_io.string).to match('Custom log formatter response')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'logs method and url' do
|
93
|
+
conn.get '/hello', nil, accept: 'text/html'
|
94
|
+
expect(string_io.string).to match('GET http:/hello')
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'logs request headers by default' do
|
98
|
+
conn.get '/hello', nil, accept: 'text/html'
|
99
|
+
expect(string_io.string).to match(%(Accept: "text/html))
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'logs response headers by default' do
|
103
|
+
conn.get '/hello', nil, accept: 'text/html'
|
104
|
+
expect(string_io.string).to match(%(Content-Type: "text/html))
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'does not log request body by default' do
|
108
|
+
conn.post '/ohai', 'name=Unagi', accept: 'text/html'
|
109
|
+
expect(string_io.string).not_to match(%(name=Unagi))
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'does not log response body by default' do
|
113
|
+
conn.post '/ohai', 'name=Toro', accept: 'text/html'
|
114
|
+
expect(string_io.string).not_to match(%(fred))
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'logs filter headers' do
|
118
|
+
conn.headers = { 'api_key' => 'ABC123' }
|
119
|
+
conn.get '/filtered_headers', nil, accept: 'text/html'
|
120
|
+
expect(string_io.string).to match(%(api_key:))
|
121
|
+
expect(string_io.string).to match(%([API_KEY]))
|
122
|
+
expect(string_io.string).not_to match(%(ABC123))
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'logs filter url' do
|
126
|
+
conn.get '/filtered_url?password=hunter2', nil, accept: 'text/html'
|
127
|
+
expect(string_io.string).to match(%([HIDDEN]))
|
128
|
+
expect(string_io.string).not_to match(%(hunter2))
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'when not logging request headers' do
|
132
|
+
let(:logger_options) { { headers: { request: false } } }
|
133
|
+
|
134
|
+
it 'does not log request headers if option is false' do
|
135
|
+
conn.get '/hello', nil, accept: 'text/html'
|
136
|
+
expect(string_io.string).not_to match(%(Accept: "text/html))
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'when not logging response headers' do
|
141
|
+
let(:logger_options) { { headers: { response: false } } }
|
142
|
+
|
143
|
+
it 'does not log response headers if option is false' do
|
144
|
+
conn.get '/hello', nil, accept: 'text/html'
|
145
|
+
expect(string_io.string).not_to match(%(Content-Type: "text/html))
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
context 'when logging request body' do
|
150
|
+
let(:logger_options) { { bodies: { request: true } } }
|
151
|
+
|
152
|
+
it 'log only request body' do
|
153
|
+
conn.post '/ohyes', 'name=Tamago', accept: 'text/html'
|
154
|
+
expect(string_io.string).to match(%(name=Tamago))
|
155
|
+
expect(string_io.string).not_to match(%(pebbles))
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
context 'when logging response body' do
|
160
|
+
let(:logger_options) { { bodies: { response: true } } }
|
161
|
+
|
162
|
+
it 'log only response body' do
|
163
|
+
conn.post '/ohyes', 'name=Hamachi', accept: 'text/html'
|
164
|
+
expect(string_io.string).to match(%(pebbles))
|
165
|
+
expect(string_io.string).not_to match(%(name=Hamachi))
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context 'when logging request and response bodies' do
|
170
|
+
let(:logger_options) { { bodies: true } }
|
171
|
+
|
172
|
+
it 'log request and response body' do
|
173
|
+
conn.post '/ohyes', 'name=Ebi', accept: 'text/html'
|
174
|
+
expect(string_io.string).to match(%(name=Ebi))
|
175
|
+
expect(string_io.string).to match(%(pebbles))
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'log response body object' do
|
179
|
+
conn.get '/rubbles', nil, accept: 'text/html'
|
180
|
+
expect(string_io.string).to match(%([\"Barney\", \"Betty\", \"Bam Bam\"]\n))
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'logs filter body' do
|
184
|
+
conn.get '/filtered_body', nil, accept: 'text/html'
|
185
|
+
expect(string_io.string).to match(%(soylent green is))
|
186
|
+
expect(string_io.string).to match(%(tasty))
|
187
|
+
expect(string_io.string).not_to match(%(people))
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
context 'when using log_level' do
|
192
|
+
let(:logger_options) { { bodies: true, log_level: :debug } }
|
193
|
+
|
194
|
+
it 'logs request/request body on the specified level (debug)' do
|
195
|
+
logger.level = Logger::DEBUG
|
196
|
+
conn.post '/ohyes', 'name=Ebi', accept: 'text/html'
|
197
|
+
expect(string_io.string).to match(%(name=Ebi))
|
198
|
+
expect(string_io.string).to match(%(pebbles))
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'logs headers on the debug level' do
|
202
|
+
logger.level = Logger::DEBUG
|
203
|
+
conn.get '/hello', nil, accept: 'text/html'
|
204
|
+
expect(string_io.string).to match(%(Content-Type: "text/html))
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'does not log request/response body on the info level' do
|
208
|
+
logger.level = Logger::INFO
|
209
|
+
conn.post '/ohyes', 'name=Ebi', accept: 'text/html'
|
210
|
+
expect(string_io.string).not_to match(%(name=Ebi))
|
211
|
+
expect(string_io.string).not_to match(%(pebbles))
|
212
|
+
end
|
213
|
+
|
214
|
+
it 'does not log headers on the info level' do
|
215
|
+
logger.level = Logger::INFO
|
216
|
+
conn.get '/hello', nil, accept: 'text/html'
|
217
|
+
expect(string_io.string).not_to match(%(Content-Type: "text/html))
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
@@ -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
|