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.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/Gemfile +5 -0
  4. data/Gemfile.lock +31 -12
  5. data/lib/oso/api.rb +18 -2
  6. data/lib/oso/version.rb +1 -1
  7. data/vendor/gems/faraday-2.5.2/CHANGELOG.md +574 -0
  8. data/vendor/gems/faraday-2.5.2/LICENSE.md +20 -0
  9. data/vendor/gems/faraday-2.5.2/README.md +55 -0
  10. data/vendor/gems/faraday-2.5.2/Rakefile +7 -0
  11. data/vendor/gems/faraday-2.5.2/examples/client_spec.rb +119 -0
  12. data/vendor/gems/faraday-2.5.2/examples/client_test.rb +144 -0
  13. data/vendor/gems/faraday-2.5.2/lib/faraday/adapter/test.rb +298 -0
  14. data/vendor/gems/faraday-2.5.2/lib/faraday/adapter.rb +102 -0
  15. data/vendor/gems/faraday-2.5.2/lib/faraday/adapter_registry.rb +30 -0
  16. data/vendor/gems/faraday-2.5.2/lib/faraday/connection.rb +561 -0
  17. data/vendor/gems/faraday-2.5.2/lib/faraday/encoders/flat_params_encoder.rb +105 -0
  18. data/vendor/gems/faraday-2.5.2/lib/faraday/encoders/nested_params_encoder.rb +183 -0
  19. data/vendor/gems/faraday-2.5.2/lib/faraday/error.rb +147 -0
  20. data/vendor/gems/faraday-2.5.2/lib/faraday/logging/formatter.rb +106 -0
  21. data/vendor/gems/faraday-2.5.2/lib/faraday/methods.rb +6 -0
  22. data/vendor/gems/faraday-2.5.2/lib/faraday/middleware.rb +30 -0
  23. data/vendor/gems/faraday-2.5.2/lib/faraday/middleware_registry.rb +83 -0
  24. data/vendor/gems/faraday-2.5.2/lib/faraday/options/connection_options.rb +22 -0
  25. data/vendor/gems/faraday-2.5.2/lib/faraday/options/env.rb +199 -0
  26. data/vendor/gems/faraday-2.5.2/lib/faraday/options/proxy_options.rb +32 -0
  27. data/vendor/gems/faraday-2.5.2/lib/faraday/options/request_options.rb +22 -0
  28. data/vendor/gems/faraday-2.5.2/lib/faraday/options/ssl_options.rb +69 -0
  29. data/vendor/gems/faraday-2.5.2/lib/faraday/options.rb +218 -0
  30. data/vendor/gems/faraday-2.5.2/lib/faraday/parameters.rb +5 -0
  31. data/vendor/gems/faraday-2.5.2/lib/faraday/rack_builder.rb +252 -0
  32. data/vendor/gems/faraday-2.5.2/lib/faraday/request/authorization.rb +49 -0
  33. data/vendor/gems/faraday-2.5.2/lib/faraday/request/instrumentation.rb +56 -0
  34. data/vendor/gems/faraday-2.5.2/lib/faraday/request/json.rb +55 -0
  35. data/vendor/gems/faraday-2.5.2/lib/faraday/request/url_encoded.rb +60 -0
  36. data/vendor/gems/faraday-2.5.2/lib/faraday/request.rb +136 -0
  37. data/vendor/gems/faraday-2.5.2/lib/faraday/response/json.rb +54 -0
  38. data/vendor/gems/faraday-2.5.2/lib/faraday/response/logger.rb +33 -0
  39. data/vendor/gems/faraday-2.5.2/lib/faraday/response/raise_error.rb +64 -0
  40. data/vendor/gems/faraday-2.5.2/lib/faraday/response.rb +90 -0
  41. data/vendor/gems/faraday-2.5.2/lib/faraday/utils/headers.rb +139 -0
  42. data/vendor/gems/faraday-2.5.2/lib/faraday/utils/params_hash.rb +61 -0
  43. data/vendor/gems/faraday-2.5.2/lib/faraday/utils.rb +122 -0
  44. data/vendor/gems/faraday-2.5.2/lib/faraday/version.rb +5 -0
  45. data/vendor/gems/faraday-2.5.2/lib/faraday.rb +157 -0
  46. data/vendor/gems/faraday-2.5.2/spec/external_adapters/faraday_specs_setup.rb +14 -0
  47. data/vendor/gems/faraday-2.5.2/spec/faraday/adapter/test_spec.rb +413 -0
  48. data/vendor/gems/faraday-2.5.2/spec/faraday/adapter_registry_spec.rb +28 -0
  49. data/vendor/gems/faraday-2.5.2/spec/faraday/adapter_spec.rb +55 -0
  50. data/vendor/gems/faraday-2.5.2/spec/faraday/connection_spec.rb +793 -0
  51. data/vendor/gems/faraday-2.5.2/spec/faraday/error_spec.rb +60 -0
  52. data/vendor/gems/faraday-2.5.2/spec/faraday/middleware_registry_spec.rb +31 -0
  53. data/vendor/gems/faraday-2.5.2/spec/faraday/middleware_spec.rb +52 -0
  54. data/vendor/gems/faraday-2.5.2/spec/faraday/options/env_spec.rb +76 -0
  55. data/vendor/gems/faraday-2.5.2/spec/faraday/options/options_spec.rb +297 -0
  56. data/vendor/gems/faraday-2.5.2/spec/faraday/options/proxy_options_spec.rb +44 -0
  57. data/vendor/gems/faraday-2.5.2/spec/faraday/options/request_options_spec.rb +19 -0
  58. data/vendor/gems/faraday-2.5.2/spec/faraday/params_encoders/flat_spec.rb +42 -0
  59. data/vendor/gems/faraday-2.5.2/spec/faraday/params_encoders/nested_spec.rb +150 -0
  60. data/vendor/gems/faraday-2.5.2/spec/faraday/rack_builder_spec.rb +317 -0
  61. data/vendor/gems/faraday-2.5.2/spec/faraday/request/authorization_spec.rb +83 -0
  62. data/vendor/gems/faraday-2.5.2/spec/faraday/request/instrumentation_spec.rb +74 -0
  63. data/vendor/gems/faraday-2.5.2/spec/faraday/request/json_spec.rb +111 -0
  64. data/vendor/gems/faraday-2.5.2/spec/faraday/request/url_encoded_spec.rb +93 -0
  65. data/vendor/gems/faraday-2.5.2/spec/faraday/request_spec.rb +110 -0
  66. data/vendor/gems/faraday-2.5.2/spec/faraday/response/json_spec.rb +117 -0
  67. data/vendor/gems/faraday-2.5.2/spec/faraday/response/logger_spec.rb +220 -0
  68. data/vendor/gems/faraday-2.5.2/spec/faraday/response/raise_error_spec.rb +172 -0
  69. data/vendor/gems/faraday-2.5.2/spec/faraday/response_spec.rb +75 -0
  70. data/vendor/gems/faraday-2.5.2/spec/faraday/utils/headers_spec.rb +82 -0
  71. data/vendor/gems/faraday-2.5.2/spec/faraday/utils_spec.rb +118 -0
  72. data/vendor/gems/faraday-2.5.2/spec/faraday_spec.rb +37 -0
  73. data/vendor/gems/faraday-2.5.2/spec/spec_helper.rb +132 -0
  74. data/vendor/gems/faraday-2.5.2/spec/support/disabling_stub.rb +14 -0
  75. data/vendor/gems/faraday-2.5.2/spec/support/fake_safe_buffer.rb +15 -0
  76. data/vendor/gems/faraday-2.5.2/spec/support/helper_methods.rb +96 -0
  77. data/vendor/gems/faraday-2.5.2/spec/support/shared_examples/adapter.rb +105 -0
  78. data/vendor/gems/faraday-2.5.2/spec/support/shared_examples/params_encoder.rb +18 -0
  79. data/vendor/gems/faraday-2.5.2/spec/support/shared_examples/request_method.rb +263 -0
  80. data/vendor/gems/faraday-2.5.2/spec/support/streaming_response_checker.rb +35 -0
  81. data/vendor/gems/faraday-net_http-3.0.2/LICENSE.md +21 -0
  82. data/vendor/gems/faraday-net_http-3.0.2/README.md +57 -0
  83. data/vendor/gems/faraday-net_http-3.0.2/lib/faraday/adapter/net_http.rb +208 -0
  84. data/vendor/gems/faraday-net_http-3.0.2/lib/faraday/net_http/version.rb +7 -0
  85. data/vendor/gems/faraday-net_http-3.0.2/lib/faraday/net_http.rb +10 -0
  86. data/vendor/gems/faraday-net_http_persistent-2.3.0/LICENSE.md +21 -0
  87. data/vendor/gems/faraday-net_http_persistent-2.3.0/README.md +66 -0
  88. data/vendor/gems/faraday-net_http_persistent-2.3.0/lib/faraday/adapter/net_http_persistent.rb +234 -0
  89. data/vendor/gems/faraday-net_http_persistent-2.3.0/lib/faraday/net_http_persistent/version.rb +7 -0
  90. data/vendor/gems/faraday-net_http_persistent-2.3.0/lib/faraday/net_http_persistent.rb +18 -0
  91. data/vendor/gems/faraday-retry-2.0.0/CHANGELOG.md +24 -0
  92. data/vendor/gems/faraday-retry-2.0.0/LICENSE.md +21 -0
  93. data/vendor/gems/faraday-retry-2.0.0/README.md +169 -0
  94. data/vendor/gems/faraday-retry-2.0.0/lib/faraday/retriable_response.rb +8 -0
  95. data/vendor/gems/faraday-retry-2.0.0/lib/faraday/retry/middleware.rb +254 -0
  96. data/vendor/gems/faraday-retry-2.0.0/lib/faraday/retry/version.rb +7 -0
  97. data/vendor/gems/faraday-retry-2.0.0/lib/faraday/retry.rb +13 -0
  98. data/vendor/gems/net-http-persistent-4.0.5/.autotest +9 -0
  99. data/vendor/gems/net-http-persistent-4.0.5/.gemtest +0 -0
  100. data/vendor/gems/net-http-persistent-4.0.5/Gemfile +14 -0
  101. data/vendor/gems/net-http-persistent-4.0.5/History.txt +460 -0
  102. data/vendor/gems/net-http-persistent-4.0.5/Manifest.txt +13 -0
  103. data/vendor/gems/net-http-persistent-4.0.5/README.rdoc +82 -0
  104. data/vendor/gems/net-http-persistent-4.0.5/Rakefile +25 -0
  105. data/vendor/gems/net-http-persistent-4.0.5/lib/net/http/persistent/connection.rb +41 -0
  106. data/vendor/gems/net-http-persistent-4.0.5/lib/net/http/persistent/pool.rb +65 -0
  107. data/vendor/gems/net-http-persistent-4.0.5/lib/net/http/persistent/timed_stack_multi.rb +79 -0
  108. data/vendor/gems/net-http-persistent-4.0.5/lib/net/http/persistent.rb +1158 -0
  109. data/vendor/gems/net-http-persistent-4.0.5/test/test_net_http_persistent.rb +1512 -0
  110. data/vendor/gems/net-http-persistent-4.0.5/test/test_net_http_persistent_timed_stack_multi.rb +151 -0
  111. 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