oso-cloud 1.9.0 → 1.9.1.pre.vendored.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/.gitignore +0 -1
- data/Gemfile +5 -0
- data/Gemfile.lock +31 -12
- data/lib/oso/api.rb +18 -2
- data/lib/oso/version.rb +1 -1
- data/vendor/gems/faraday-2.5.2/CHANGELOG.md +574 -0
- data/vendor/gems/faraday-2.5.2/LICENSE.md +20 -0
- data/vendor/gems/faraday-2.5.2/README.md +55 -0
- data/vendor/gems/faraday-2.5.2/Rakefile +7 -0
- data/vendor/gems/faraday-2.5.2/examples/client_spec.rb +119 -0
- data/vendor/gems/faraday-2.5.2/examples/client_test.rb +144 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/adapter/test.rb +298 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/adapter.rb +102 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/adapter_registry.rb +30 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/connection.rb +561 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/encoders/flat_params_encoder.rb +105 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/encoders/nested_params_encoder.rb +183 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/error.rb +147 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/logging/formatter.rb +106 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/methods.rb +6 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/middleware.rb +30 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/middleware_registry.rb +83 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/options/connection_options.rb +22 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/options/env.rb +199 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/options/proxy_options.rb +32 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/options/request_options.rb +22 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/options/ssl_options.rb +69 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/options.rb +218 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/parameters.rb +5 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/rack_builder.rb +252 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/request/authorization.rb +49 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/request/instrumentation.rb +56 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/request/json.rb +55 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/request/url_encoded.rb +60 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/request.rb +136 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/response/json.rb +54 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/response/logger.rb +33 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/response/raise_error.rb +64 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/response.rb +90 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/utils/headers.rb +139 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/utils/params_hash.rb +61 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/utils.rb +122 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday/version.rb +5 -0
- data/vendor/gems/faraday-2.5.2/lib/faraday.rb +157 -0
- data/vendor/gems/faraday-2.5.2/spec/external_adapters/faraday_specs_setup.rb +14 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/adapter/test_spec.rb +413 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/adapter_registry_spec.rb +28 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/adapter_spec.rb +55 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/connection_spec.rb +793 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/error_spec.rb +60 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/middleware_registry_spec.rb +31 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/middleware_spec.rb +52 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/options/env_spec.rb +76 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/options/options_spec.rb +297 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/options/proxy_options_spec.rb +44 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/options/request_options_spec.rb +19 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/params_encoders/flat_spec.rb +42 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/params_encoders/nested_spec.rb +150 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/rack_builder_spec.rb +317 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/request/authorization_spec.rb +83 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/request/instrumentation_spec.rb +74 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/request/json_spec.rb +111 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/request/url_encoded_spec.rb +93 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/request_spec.rb +110 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/response/json_spec.rb +117 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/response/logger_spec.rb +220 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/response/raise_error_spec.rb +172 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/response_spec.rb +75 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/utils/headers_spec.rb +82 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday/utils_spec.rb +118 -0
- data/vendor/gems/faraday-2.5.2/spec/faraday_spec.rb +37 -0
- data/vendor/gems/faraday-2.5.2/spec/spec_helper.rb +132 -0
- data/vendor/gems/faraday-2.5.2/spec/support/disabling_stub.rb +14 -0
- data/vendor/gems/faraday-2.5.2/spec/support/fake_safe_buffer.rb +15 -0
- data/vendor/gems/faraday-2.5.2/spec/support/helper_methods.rb +96 -0
- data/vendor/gems/faraday-2.5.2/spec/support/shared_examples/adapter.rb +105 -0
- data/vendor/gems/faraday-2.5.2/spec/support/shared_examples/params_encoder.rb +18 -0
- data/vendor/gems/faraday-2.5.2/spec/support/shared_examples/request_method.rb +263 -0
- data/vendor/gems/faraday-2.5.2/spec/support/streaming_response_checker.rb +35 -0
- data/vendor/gems/faraday-net_http-3.0.2/LICENSE.md +21 -0
- data/vendor/gems/faraday-net_http-3.0.2/README.md +57 -0
- data/vendor/gems/faraday-net_http-3.0.2/lib/faraday/adapter/net_http.rb +208 -0
- data/vendor/gems/faraday-net_http-3.0.2/lib/faraday/net_http/version.rb +7 -0
- data/vendor/gems/faraday-net_http-3.0.2/lib/faraday/net_http.rb +10 -0
- data/vendor/gems/faraday-net_http_persistent-2.3.0/LICENSE.md +21 -0
- data/vendor/gems/faraday-net_http_persistent-2.3.0/README.md +66 -0
- data/vendor/gems/faraday-net_http_persistent-2.3.0/lib/faraday/adapter/net_http_persistent.rb +234 -0
- data/vendor/gems/faraday-net_http_persistent-2.3.0/lib/faraday/net_http_persistent/version.rb +7 -0
- data/vendor/gems/faraday-net_http_persistent-2.3.0/lib/faraday/net_http_persistent.rb +18 -0
- data/vendor/gems/faraday-retry-2.0.0/CHANGELOG.md +24 -0
- data/vendor/gems/faraday-retry-2.0.0/LICENSE.md +21 -0
- data/vendor/gems/faraday-retry-2.0.0/README.md +169 -0
- data/vendor/gems/faraday-retry-2.0.0/lib/faraday/retriable_response.rb +8 -0
- data/vendor/gems/faraday-retry-2.0.0/lib/faraday/retry/middleware.rb +254 -0
- data/vendor/gems/faraday-retry-2.0.0/lib/faraday/retry/version.rb +7 -0
- data/vendor/gems/faraday-retry-2.0.0/lib/faraday/retry.rb +13 -0
- data/vendor/gems/net-http-persistent-4.0.5/.autotest +9 -0
- data/vendor/gems/net-http-persistent-4.0.5/.gemtest +0 -0
- data/vendor/gems/net-http-persistent-4.0.5/Gemfile +14 -0
- data/vendor/gems/net-http-persistent-4.0.5/History.txt +460 -0
- data/vendor/gems/net-http-persistent-4.0.5/Manifest.txt +13 -0
- data/vendor/gems/net-http-persistent-4.0.5/README.rdoc +82 -0
- data/vendor/gems/net-http-persistent-4.0.5/Rakefile +25 -0
- data/vendor/gems/net-http-persistent-4.0.5/lib/net/http/persistent/connection.rb +41 -0
- data/vendor/gems/net-http-persistent-4.0.5/lib/net/http/persistent/pool.rb +65 -0
- data/vendor/gems/net-http-persistent-4.0.5/lib/net/http/persistent/timed_stack_multi.rb +79 -0
- data/vendor/gems/net-http-persistent-4.0.5/lib/net/http/persistent.rb +1158 -0
- data/vendor/gems/net-http-persistent-4.0.5/test/test_net_http_persistent.rb +1512 -0
- data/vendor/gems/net-http-persistent-4.0.5/test/test_net_http_persistent_timed_stack_multi.rb +151 -0
- metadata +108 -4
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Faraday::Request::Json do
|
4
|
+
let(:middleware) { described_class.new(->(env) { Faraday::Response.new(env) }) }
|
5
|
+
|
6
|
+
def process(body, content_type = nil)
|
7
|
+
env = { body: body, request_headers: Faraday::Utils::Headers.new }
|
8
|
+
env[:request_headers]['content-type'] = content_type if content_type
|
9
|
+
middleware.call(Faraday::Env.from(env)).env
|
10
|
+
end
|
11
|
+
|
12
|
+
def result_body
|
13
|
+
result[:body]
|
14
|
+
end
|
15
|
+
|
16
|
+
def result_type
|
17
|
+
result[:request_headers]['content-type']
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'no body' do
|
21
|
+
let(:result) { process(nil) }
|
22
|
+
|
23
|
+
it "doesn't change body" do
|
24
|
+
expect(result_body).to be_nil
|
25
|
+
end
|
26
|
+
|
27
|
+
it "doesn't add content type" do
|
28
|
+
expect(result_type).to be_nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'empty body' do
|
33
|
+
let(:result) { process('') }
|
34
|
+
|
35
|
+
it "doesn't change body" do
|
36
|
+
expect(result_body).to be_empty
|
37
|
+
end
|
38
|
+
|
39
|
+
it "doesn't add content type" do
|
40
|
+
expect(result_type).to be_nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'string body' do
|
45
|
+
let(:result) { process('{"a":1}') }
|
46
|
+
|
47
|
+
it "doesn't change body" do
|
48
|
+
expect(result_body).to eq('{"a":1}')
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'adds content type' do
|
52
|
+
expect(result_type).to eq('application/json')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'object body' do
|
57
|
+
let(:result) { process(a: 1) }
|
58
|
+
|
59
|
+
it 'encodes body' do
|
60
|
+
expect(result_body).to eq('{"a":1}')
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'adds content type' do
|
64
|
+
expect(result_type).to eq('application/json')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'empty object body' do
|
69
|
+
let(:result) { process({}) }
|
70
|
+
|
71
|
+
it 'encodes body' do
|
72
|
+
expect(result_body).to eq('{}')
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'object body with json type' do
|
77
|
+
let(:result) { process({ a: 1 }, 'application/json; charset=utf-8') }
|
78
|
+
|
79
|
+
it 'encodes body' do
|
80
|
+
expect(result_body).to eq('{"a":1}')
|
81
|
+
end
|
82
|
+
|
83
|
+
it "doesn't change content type" do
|
84
|
+
expect(result_type).to eq('application/json; charset=utf-8')
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'object body with vendor json type' do
|
89
|
+
let(:result) { process({ a: 1 }, 'application/vnd.myapp.v1+json; charset=utf-8') }
|
90
|
+
|
91
|
+
it 'encodes body' do
|
92
|
+
expect(result_body).to eq('{"a":1}')
|
93
|
+
end
|
94
|
+
|
95
|
+
it "doesn't change content type" do
|
96
|
+
expect(result_type).to eq('application/vnd.myapp.v1+json; charset=utf-8')
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'object body with incompatible type' do
|
101
|
+
let(:result) { process({ a: 1 }, 'application/xml; charset=utf-8') }
|
102
|
+
|
103
|
+
it "doesn't change body" do
|
104
|
+
expect(result_body).to eq(a: 1)
|
105
|
+
end
|
106
|
+
|
107
|
+
it "doesn't change content type" do
|
108
|
+
expect(result_type).to eq('application/xml; charset=utf-8')
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
RSpec.describe Faraday::Request::UrlEncoded do
|
6
|
+
let(:conn) do
|
7
|
+
Faraday.new do |b|
|
8
|
+
b.request :url_encoded
|
9
|
+
b.adapter :test do |stub|
|
10
|
+
stub.post('/echo') do |env|
|
11
|
+
posted_as = env[:request_headers]['Content-Type']
|
12
|
+
body = env[:body]
|
13
|
+
if body.respond_to?(:read)
|
14
|
+
body = body.read
|
15
|
+
end
|
16
|
+
[200, { 'Content-Type' => posted_as }, body]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'does nothing without payload' do
|
23
|
+
response = conn.post('/echo')
|
24
|
+
expect(response.headers['Content-Type']).to be_nil
|
25
|
+
expect(response.body.empty?).to be_truthy
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'ignores custom content type' do
|
29
|
+
response = conn.post('/echo', { some: 'data' }, 'content-type' => 'application/x-foo')
|
30
|
+
expect(response.headers['Content-Type']).to eq('application/x-foo')
|
31
|
+
expect(response.body).to eq(some: 'data')
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'works with no headers' do
|
35
|
+
response = conn.post('/echo', fruit: %w[apples oranges])
|
36
|
+
expect(response.headers['Content-Type']).to eq('application/x-www-form-urlencoded')
|
37
|
+
expect(response.body).to eq('fruit%5B%5D=apples&fruit%5B%5D=oranges')
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'works with with headers' do
|
41
|
+
response = conn.post('/echo', { 'a' => 123 }, 'content-type' => 'application/x-www-form-urlencoded')
|
42
|
+
expect(response.headers['Content-Type']).to eq('application/x-www-form-urlencoded')
|
43
|
+
expect(response.body).to eq('a=123')
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'works with nested params' do
|
47
|
+
response = conn.post('/echo', user: { name: 'Mislav', web: 'mislav.net' })
|
48
|
+
expect(response.headers['Content-Type']).to eq('application/x-www-form-urlencoded')
|
49
|
+
expected = { 'user' => { 'name' => 'Mislav', 'web' => 'mislav.net' } }
|
50
|
+
expect(Faraday::Utils.parse_nested_query(response.body)).to eq(expected)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'works with non nested params' do
|
54
|
+
response = conn.post('/echo', dimensions: %w[date location]) do |req|
|
55
|
+
req.options.params_encoder = Faraday::FlatParamsEncoder
|
56
|
+
end
|
57
|
+
expect(response.headers['Content-Type']).to eq('application/x-www-form-urlencoded')
|
58
|
+
expected = { 'dimensions' => %w[date location] }
|
59
|
+
expect(Faraday::Utils.parse_query(response.body)).to eq(expected)
|
60
|
+
expect(response.body).to eq('dimensions=date&dimensions=location')
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'works with unicode' do
|
64
|
+
err = capture_warnings do
|
65
|
+
response = conn.post('/echo', str: 'eé cç aã aâ')
|
66
|
+
expect(response.body).to eq('str=e%C3%A9+c%C3%A7+a%C3%A3+a%C3%A2')
|
67
|
+
end
|
68
|
+
expect(err.empty?).to be_truthy
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'works with nested keys' do
|
72
|
+
response = conn.post('/echo', 'a' => { 'b' => { 'c' => ['d'] } })
|
73
|
+
expect(response.body).to eq('a%5Bb%5D%5Bc%5D%5B%5D=d')
|
74
|
+
end
|
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
|
+
|
81
|
+
context 'customising default_space_encoding' do
|
82
|
+
around do |example|
|
83
|
+
Faraday::Utils.default_space_encoding = '%20'
|
84
|
+
example.run
|
85
|
+
Faraday::Utils.default_space_encoding = nil
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'uses the custom character to encode spaces' do
|
89
|
+
response = conn.post('/echo', str: 'apple banana')
|
90
|
+
expect(response.body).to eq('str=apple%20banana')
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Faraday::Request do
|
4
|
+
let(:conn) do
|
5
|
+
Faraday.new(url: 'http://httpbingo.org/api',
|
6
|
+
headers: { 'Mime-Version' => '1.0' },
|
7
|
+
request: { oauth: { consumer_key: 'anonymous' } })
|
8
|
+
end
|
9
|
+
let(:http_method) { :get }
|
10
|
+
let(:block) { nil }
|
11
|
+
|
12
|
+
subject { conn.build_request(http_method, &block) }
|
13
|
+
|
14
|
+
context 'when nothing particular is configured' do
|
15
|
+
it { expect(subject.http_method).to eq(:get) }
|
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 }
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'when HTTP method is post' do
|
21
|
+
let(:http_method) { :post }
|
22
|
+
|
23
|
+
it { expect(subject.http_method).to eq(:post) }
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'when setting the url on setup with a URI' do
|
27
|
+
let(:block) { proc { |req| req.url URI.parse('foo.json?a=1') } }
|
28
|
+
|
29
|
+
it { expect(subject.path).to eq(URI.parse('foo.json')) }
|
30
|
+
it { expect(subject.params).to eq('a' => '1') }
|
31
|
+
it { expect(subject.to_env(conn).url.to_s).to eq('http://httpbingo.org/api/foo.json?a=1') }
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when setting the url on setup with a string path and params' do
|
35
|
+
let(:block) { proc { |req| req.url 'foo.json', 'a' => 1 } }
|
36
|
+
|
37
|
+
it { expect(subject.path).to eq('foo.json') }
|
38
|
+
it { expect(subject.params).to eq('a' => 1) }
|
39
|
+
it { expect(subject.to_env(conn).url.to_s).to eq('http://httpbingo.org/api/foo.json?a=1') }
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'when setting the url on setup with a path including params' do
|
43
|
+
let(:block) { proc { |req| req.url 'foo.json?b=2&a=1#qqq' } }
|
44
|
+
|
45
|
+
it { expect(subject.path).to eq('foo.json') }
|
46
|
+
it { expect(subject.params).to eq('a' => '1', 'b' => '2') }
|
47
|
+
it { expect(subject.to_env(conn).url.to_s).to eq('http://httpbingo.org/api/foo.json?a=1&b=2') }
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'when setting a header on setup with []= syntax' do
|
51
|
+
let(:block) { proc { |req| req['Server'] = 'Faraday' } }
|
52
|
+
let(:headers) { subject.to_env(conn).request_headers }
|
53
|
+
|
54
|
+
it { expect(subject.headers['Server']).to eq('Faraday') }
|
55
|
+
it { expect(headers['mime-version']).to eq('1.0') }
|
56
|
+
it { expect(headers['server']).to eq('Faraday') }
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'when setting the body on setup' do
|
60
|
+
let(:block) { proc { |req| req.body = 'hi' } }
|
61
|
+
|
62
|
+
it { expect(subject.body).to eq('hi') }
|
63
|
+
it { expect(subject.to_env(conn).body).to eq('hi') }
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'with global request options set' do
|
67
|
+
let(:env_request) { subject.to_env(conn).request }
|
68
|
+
|
69
|
+
before do
|
70
|
+
conn.options.timeout = 3
|
71
|
+
conn.options.open_timeout = 5
|
72
|
+
conn.ssl.verify = false
|
73
|
+
conn.proxy = 'http://proxy.com'
|
74
|
+
end
|
75
|
+
|
76
|
+
it { expect(subject.options.timeout).to eq(3) }
|
77
|
+
it { expect(subject.options.open_timeout).to eq(5) }
|
78
|
+
it { expect(env_request.timeout).to eq(3) }
|
79
|
+
it { expect(env_request.open_timeout).to eq(5) }
|
80
|
+
|
81
|
+
context 'and per-request options set' do
|
82
|
+
let(:block) do
|
83
|
+
proc do |req|
|
84
|
+
req.options.timeout = 10
|
85
|
+
req.options.boundary = 'boo'
|
86
|
+
req.options.oauth[:consumer_secret] = 'xyz'
|
87
|
+
req.options.context = {
|
88
|
+
foo: 'foo',
|
89
|
+
bar: 'bar'
|
90
|
+
}
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
it { expect(subject.options.timeout).to eq(10) }
|
95
|
+
it { expect(subject.options.open_timeout).to eq(5) }
|
96
|
+
it { expect(env_request.timeout).to eq(10) }
|
97
|
+
it { expect(env_request.open_timeout).to eq(5) }
|
98
|
+
it { expect(env_request.boundary).to eq('boo') }
|
99
|
+
it { expect(env_request.context).to eq(foo: 'foo', bar: 'bar') }
|
100
|
+
it do
|
101
|
+
oauth_expected = { consumer_secret: 'xyz', consumer_key: 'anonymous' }
|
102
|
+
expect(env_request.oauth).to eq(oauth_expected)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'supports marshal serialization' do
|
108
|
+
expect(Marshal.load(Marshal.dump(subject))).to eq(subject)
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Faraday::Response::Json, type: :response do
|
4
|
+
let(:options) { {} }
|
5
|
+
let(:headers) { {} }
|
6
|
+
let(:middleware) do
|
7
|
+
described_class.new(lambda { |env|
|
8
|
+
Faraday::Response.new(env)
|
9
|
+
}, **options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def process(body, content_type = 'application/json', options = {})
|
13
|
+
env = {
|
14
|
+
body: body, request: options,
|
15
|
+
request_headers: Faraday::Utils::Headers.new,
|
16
|
+
response_headers: Faraday::Utils::Headers.new(headers)
|
17
|
+
}
|
18
|
+
env[:response_headers]['content-type'] = content_type if content_type
|
19
|
+
yield(env) if block_given?
|
20
|
+
middleware.call(Faraday::Env.from(env))
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'no type matching' do
|
24
|
+
it "doesn't change nil body" do
|
25
|
+
expect(process(nil).body).to be_nil
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'nullifies empty body' do
|
29
|
+
expect(process('').body).to be_nil
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'parses json body' do
|
33
|
+
response = process('{"a":1}')
|
34
|
+
expect(response.body).to eq('a' => 1)
|
35
|
+
expect(response.env[:raw_body]).to be_nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'with preserving raw' do
|
40
|
+
let(:options) { { preserve_raw: true } }
|
41
|
+
|
42
|
+
it 'parses json body' do
|
43
|
+
response = process('{"a":1}')
|
44
|
+
expect(response.body).to eq('a' => 1)
|
45
|
+
expect(response.env[:raw_body]).to eq('{"a":1}')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'with default regexp type matching' do
|
50
|
+
it 'parses json body of correct type' do
|
51
|
+
response = process('{"a":1}', 'application/x-json')
|
52
|
+
expect(response.body).to eq('a' => 1)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'ignores json body of incorrect type' do
|
56
|
+
response = process('{"a":1}', 'text/json-xml')
|
57
|
+
expect(response.body).to eq('{"a":1}')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'with array type matching' do
|
62
|
+
let(:options) { { content_type: %w[a/b c/d] } }
|
63
|
+
|
64
|
+
it 'parses json body of correct type' do
|
65
|
+
expect(process('{"a":1}', 'a/b').body).to be_a(Hash)
|
66
|
+
expect(process('{"a":1}', 'c/d').body).to be_a(Hash)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'ignores json body of incorrect type' do
|
70
|
+
expect(process('{"a":1}', 'a/d').body).not_to be_a(Hash)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'chokes on invalid json' do
|
75
|
+
expect { process('{!') }.to raise_error(Faraday::ParsingError)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'includes the response on the ParsingError instance' do
|
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)
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'HEAD responses' do
|
86
|
+
it "nullifies the body if it's only one space" do
|
87
|
+
response = process(' ')
|
88
|
+
expect(response.body).to be_nil
|
89
|
+
end
|
90
|
+
|
91
|
+
it "nullifies the body if it's two spaces" do
|
92
|
+
response = process(' ')
|
93
|
+
expect(response.body).to be_nil
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context 'JSON options' do
|
98
|
+
let(:body) { '{"a": 1}' }
|
99
|
+
let(:result) { { a: 1 } }
|
100
|
+
let(:options) do
|
101
|
+
{
|
102
|
+
parser_options: {
|
103
|
+
symbolize_names: true
|
104
|
+
}
|
105
|
+
}
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'passes relevant options to JSON parse' do
|
109
|
+
expect(::JSON).to receive(:parse)
|
110
|
+
.with(body, options[:parser_options])
|
111
|
+
.and_return(result)
|
112
|
+
|
113
|
+
response = process(body)
|
114
|
+
expect(response.body).to eq(result)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
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
|