oso-cloud 1.8.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/README.md +1 -1
- data/lib/oso/api.rb +18 -2
- data/lib/oso/oso.rb +10 -7
- 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 +112 -8
@@ -0,0 +1,119 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Requires Ruby with rspec and faraday gems.
|
4
|
+
# rspec client_spec.rb
|
5
|
+
|
6
|
+
require 'faraday'
|
7
|
+
require 'json'
|
8
|
+
|
9
|
+
# Example API client
|
10
|
+
class Client
|
11
|
+
def initialize(conn)
|
12
|
+
@conn = conn
|
13
|
+
end
|
14
|
+
|
15
|
+
def httpbingo(jname, params: {})
|
16
|
+
res = @conn.get("/#{jname}", params)
|
17
|
+
data = JSON.parse(res.body)
|
18
|
+
data['origin']
|
19
|
+
end
|
20
|
+
|
21
|
+
def foo(params)
|
22
|
+
res = @conn.post('/foo', JSON.dump(params))
|
23
|
+
res.status
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
RSpec.describe Client do
|
28
|
+
let(:stubs) { Faraday::Adapter::Test::Stubs.new }
|
29
|
+
let(:conn) { Faraday.new { |b| b.adapter(:test, stubs) } }
|
30
|
+
let(:client) { Client.new(conn) }
|
31
|
+
|
32
|
+
it 'parses origin' do
|
33
|
+
stubs.get('/ip') do |env|
|
34
|
+
# optional: you can inspect the Faraday::Env
|
35
|
+
expect(env.url.path).to eq('/ip')
|
36
|
+
[
|
37
|
+
200,
|
38
|
+
{ 'Content-Type': 'application/javascript' },
|
39
|
+
'{"origin": "127.0.0.1"}'
|
40
|
+
]
|
41
|
+
end
|
42
|
+
|
43
|
+
# uncomment to trigger stubs.verify_stubbed_calls failure
|
44
|
+
# stubs.get('/unused') { [404, {}, ''] }
|
45
|
+
|
46
|
+
expect(client.httpbingo('ip')).to eq('127.0.0.1')
|
47
|
+
stubs.verify_stubbed_calls
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'handles 404' do
|
51
|
+
stubs.get('/api') do
|
52
|
+
[
|
53
|
+
404,
|
54
|
+
{ 'Content-Type': 'application/javascript' },
|
55
|
+
'{}'
|
56
|
+
]
|
57
|
+
end
|
58
|
+
expect(client.httpbingo('api')).to be_nil
|
59
|
+
stubs.verify_stubbed_calls
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'handles exception' do
|
63
|
+
stubs.get('/api') do
|
64
|
+
raise Faraday::ConnectionFailed
|
65
|
+
end
|
66
|
+
|
67
|
+
expect { client.httpbingo('api') }.to raise_error(Faraday::ConnectionFailed)
|
68
|
+
stubs.verify_stubbed_calls
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'When the test stub is run in strict_mode' do
|
72
|
+
let(:stubs) { Faraday::Adapter::Test::Stubs.new(strict_mode: true) }
|
73
|
+
|
74
|
+
it 'verifies the all parameter values are identical' do
|
75
|
+
stubs.get('/api?abc=123') do
|
76
|
+
[
|
77
|
+
200,
|
78
|
+
{ 'Content-Type': 'application/javascript' },
|
79
|
+
'{"origin": "127.0.0.1"}'
|
80
|
+
]
|
81
|
+
end
|
82
|
+
|
83
|
+
# uncomment to raise Stubs::NotFound
|
84
|
+
# expect(client.httpbingo('api', params: { abc: 123, foo: 'Kappa' })).to eq('127.0.0.1')
|
85
|
+
expect(client.httpbingo('api', params: { abc: 123 })).to eq('127.0.0.1')
|
86
|
+
stubs.verify_stubbed_calls
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'When the Faraday connection is configured with FlatParamsEncoder' do
|
91
|
+
let(:conn) { Faraday.new(request: { params_encoder: Faraday::FlatParamsEncoder }) { |b| b.adapter(:test, stubs) } }
|
92
|
+
|
93
|
+
it 'handles the same multiple URL parameters' do
|
94
|
+
stubs.get('/api?a=x&a=y&a=z') { [200, { 'Content-Type' => 'application/json' }, '{"origin": "127.0.0.1"}'] }
|
95
|
+
|
96
|
+
# uncomment to raise Stubs::NotFound
|
97
|
+
# expect(client.httpbingo('api', params: { a: %w[x y] })).to eq('127.0.0.1')
|
98
|
+
expect(client.httpbingo('api', params: { a: %w[x y z] })).to eq('127.0.0.1')
|
99
|
+
stubs.verify_stubbed_calls
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context 'When you want to test the body, you can use a proc as well as string' do
|
104
|
+
it 'tests with a string' do
|
105
|
+
stubs.post('/foo', '{"name":"YK"}') { [200, {}, ''] }
|
106
|
+
|
107
|
+
expect(client.foo(name: 'YK')).to eq 200
|
108
|
+
stubs.verify_stubbed_calls
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'tests with a proc' do
|
112
|
+
check = ->(request_body) { JSON.parse(request_body).slice('name') == { 'name' => 'YK' } }
|
113
|
+
stubs.post('/foo', check) { [200, {}, ''] }
|
114
|
+
|
115
|
+
expect(client.foo(name: 'YK', created_at: Time.now)).to eq 200
|
116
|
+
stubs.verify_stubbed_calls
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Requires Ruby with test-unit and faraday gems.
|
4
|
+
# ruby client_test.rb
|
5
|
+
|
6
|
+
require 'faraday'
|
7
|
+
require 'json'
|
8
|
+
require 'test/unit'
|
9
|
+
|
10
|
+
# Example API client
|
11
|
+
class Client
|
12
|
+
def initialize(conn)
|
13
|
+
@conn = conn
|
14
|
+
end
|
15
|
+
|
16
|
+
def httpbingo(jname, params: {})
|
17
|
+
res = @conn.get("/#{jname}", params)
|
18
|
+
data = JSON.parse(res.body)
|
19
|
+
data['origin']
|
20
|
+
end
|
21
|
+
|
22
|
+
def foo(params)
|
23
|
+
res = @conn.post('/foo', JSON.dump(params))
|
24
|
+
res.status
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Example API client test
|
29
|
+
class ClientTest < Test::Unit::TestCase
|
30
|
+
def test_httpbingo_name
|
31
|
+
stubs = Faraday::Adapter::Test::Stubs.new
|
32
|
+
stubs.get('/api') do |env|
|
33
|
+
# optional: you can inspect the Faraday::Env
|
34
|
+
assert_equal '/api', env.url.path
|
35
|
+
[
|
36
|
+
200,
|
37
|
+
{ 'Content-Type': 'application/javascript' },
|
38
|
+
'{"origin": "127.0.0.1"}'
|
39
|
+
]
|
40
|
+
end
|
41
|
+
|
42
|
+
# uncomment to trigger stubs.verify_stubbed_calls failure
|
43
|
+
# stubs.get('/unused') { [404, {}, ''] }
|
44
|
+
|
45
|
+
cli = client(stubs)
|
46
|
+
assert_equal '127.0.0.1', cli.httpbingo('api')
|
47
|
+
stubs.verify_stubbed_calls
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_httpbingo_not_found
|
51
|
+
stubs = Faraday::Adapter::Test::Stubs.new
|
52
|
+
stubs.get('/api') do
|
53
|
+
[
|
54
|
+
404,
|
55
|
+
{ 'Content-Type': 'application/javascript' },
|
56
|
+
'{}'
|
57
|
+
]
|
58
|
+
end
|
59
|
+
|
60
|
+
cli = client(stubs)
|
61
|
+
assert_nil cli.httpbingo('api')
|
62
|
+
stubs.verify_stubbed_calls
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_httpbingo_exception
|
66
|
+
stubs = Faraday::Adapter::Test::Stubs.new
|
67
|
+
stubs.get('/api') do
|
68
|
+
raise Faraday::ConnectionFailed
|
69
|
+
end
|
70
|
+
|
71
|
+
cli = client(stubs)
|
72
|
+
assert_raise Faraday::ConnectionFailed do
|
73
|
+
cli.httpbingo('api')
|
74
|
+
end
|
75
|
+
stubs.verify_stubbed_calls
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_strict_mode
|
79
|
+
stubs = Faraday::Adapter::Test::Stubs.new(strict_mode: true)
|
80
|
+
stubs.get('/api?abc=123') do
|
81
|
+
[
|
82
|
+
200,
|
83
|
+
{ 'Content-Type': 'application/javascript' },
|
84
|
+
'{"origin": "127.0.0.1"}'
|
85
|
+
]
|
86
|
+
end
|
87
|
+
|
88
|
+
cli = client(stubs)
|
89
|
+
assert_equal '127.0.0.1', cli.httpbingo('api', params: { abc: 123 })
|
90
|
+
|
91
|
+
# uncomment to raise Stubs::NotFound
|
92
|
+
# assert_equal '127.0.0.1', cli.httpbingo('api', params: { abc: 123, foo: 'Kappa' })
|
93
|
+
stubs.verify_stubbed_calls
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_non_default_params_encoder
|
97
|
+
stubs = Faraday::Adapter::Test::Stubs.new(strict_mode: true)
|
98
|
+
stubs.get('/api?a=x&a=y&a=z') do
|
99
|
+
[
|
100
|
+
200,
|
101
|
+
{ 'Content-Type': 'application/javascript' },
|
102
|
+
'{"origin": "127.0.0.1"}'
|
103
|
+
]
|
104
|
+
end
|
105
|
+
conn = Faraday.new(request: { params_encoder: Faraday::FlatParamsEncoder }) do |builder|
|
106
|
+
builder.adapter :test, stubs
|
107
|
+
end
|
108
|
+
|
109
|
+
cli = Client.new(conn)
|
110
|
+
assert_equal '127.0.0.1', cli.httpbingo('api', params: { a: %w[x y z] })
|
111
|
+
|
112
|
+
# uncomment to raise Stubs::NotFound
|
113
|
+
# assert_equal '127.0.0.1', cli.httpbingo('api', params: { a: %w[x y] })
|
114
|
+
stubs.verify_stubbed_calls
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_with_string_body
|
118
|
+
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
119
|
+
stub.post('/foo', '{"name":"YK"}') { [200, {}, ''] }
|
120
|
+
end
|
121
|
+
cli = client(stubs)
|
122
|
+
assert_equal 200, cli.foo(name: 'YK')
|
123
|
+
|
124
|
+
stubs.verify_stubbed_calls
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_with_proc_body
|
128
|
+
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
129
|
+
check = ->(request_body) { JSON.parse(request_body).slice('name') == { 'name' => 'YK' } }
|
130
|
+
stub.post('/foo', check) { [200, {}, ''] }
|
131
|
+
end
|
132
|
+
cli = client(stubs)
|
133
|
+
assert_equal 200, cli.foo(name: 'YK', created_at: Time.now)
|
134
|
+
|
135
|
+
stubs.verify_stubbed_calls
|
136
|
+
end
|
137
|
+
|
138
|
+
def client(stubs)
|
139
|
+
conn = Faraday.new do |builder|
|
140
|
+
builder.adapter :test, stubs
|
141
|
+
end
|
142
|
+
Client.new(conn)
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,298 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Faraday
|
4
|
+
class Adapter
|
5
|
+
# @example
|
6
|
+
# test = Faraday::Connection.new do
|
7
|
+
# use Faraday::Adapter::Test do |stub|
|
8
|
+
# # Define matcher to match the request
|
9
|
+
# stub.get '/resource.json' do
|
10
|
+
# # return static content
|
11
|
+
# [200, {'Content-Type' => 'application/json'}, 'hi world']
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# # response with content generated based on request
|
15
|
+
# stub.get '/showget' do |env|
|
16
|
+
# [200, {'Content-Type' => 'text/plain'}, env[:method].to_s]
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# # A regular expression can be used as matching filter
|
20
|
+
# stub.get /\A\/items\/(\d+)\z/ do |env, meta|
|
21
|
+
# # in case regular expression is used, an instance of MatchData
|
22
|
+
# # can be received
|
23
|
+
# [200,
|
24
|
+
# {'Content-Type' => 'text/plain'},
|
25
|
+
# "showing item: #{meta[:match_data][1]}"
|
26
|
+
# ]
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# # Test the request body is the same as the stubbed body
|
30
|
+
# stub.post('/bar', 'name=YK&word=call') { [200, {}, ''] }
|
31
|
+
#
|
32
|
+
# # You can pass a proc as a stubbed body and check the request body in your way.
|
33
|
+
# # In this case, the proc should return true or false.
|
34
|
+
# stub.post('/foo', ->(request_body) do
|
35
|
+
# JSON.parse(request_body).slice('name') == { 'name' => 'YK' } }) { [200, {}, '']
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# # You can set strict_mode to exactly match the stubbed requests.
|
39
|
+
# stub.strict_mode = true
|
40
|
+
# end
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# resp = test.get '/resource.json'
|
44
|
+
# resp.body # => 'hi world'
|
45
|
+
#
|
46
|
+
# resp = test.get '/showget'
|
47
|
+
# resp.body # => 'get'
|
48
|
+
#
|
49
|
+
# resp = test.get '/items/1'
|
50
|
+
# resp.body # => 'showing item: 1'
|
51
|
+
#
|
52
|
+
# resp = test.get '/items/2'
|
53
|
+
# resp.body # => 'showing item: 2'
|
54
|
+
#
|
55
|
+
# resp = test.post '/bar', 'name=YK&word=call'
|
56
|
+
# resp.status # => 200
|
57
|
+
#
|
58
|
+
# resp = test.post '/foo', JSON.dump(name: 'YK', created_at: Time.now)
|
59
|
+
# resp.status # => 200
|
60
|
+
class Test < Faraday::Adapter
|
61
|
+
attr_accessor :stubs
|
62
|
+
|
63
|
+
# A stack of Stubs
|
64
|
+
class Stubs
|
65
|
+
class NotFound < StandardError
|
66
|
+
end
|
67
|
+
|
68
|
+
def initialize(strict_mode: false)
|
69
|
+
# { get: [Stub, Stub] }
|
70
|
+
@stack = {}
|
71
|
+
@consumed = {}
|
72
|
+
@strict_mode = strict_mode
|
73
|
+
@stubs_mutex = Monitor.new
|
74
|
+
yield(self) if block_given?
|
75
|
+
end
|
76
|
+
|
77
|
+
def empty?
|
78
|
+
@stack.empty?
|
79
|
+
end
|
80
|
+
|
81
|
+
# @param env [Faraday::Env]
|
82
|
+
def match(env)
|
83
|
+
request_method = env[:method]
|
84
|
+
return false unless @stack.key?(request_method)
|
85
|
+
|
86
|
+
stack = @stack[request_method]
|
87
|
+
consumed = (@consumed[request_method] ||= [])
|
88
|
+
|
89
|
+
@stubs_mutex.synchronize do
|
90
|
+
stub, meta = matches?(stack, env)
|
91
|
+
if stub
|
92
|
+
removed = stack.delete(stub)
|
93
|
+
consumed << removed unless removed.nil?
|
94
|
+
return stub, meta
|
95
|
+
end
|
96
|
+
end
|
97
|
+
matches?(consumed, env)
|
98
|
+
end
|
99
|
+
|
100
|
+
def get(path, headers = {}, &block)
|
101
|
+
new_stub(:get, path, headers, &block)
|
102
|
+
end
|
103
|
+
|
104
|
+
def head(path, headers = {}, &block)
|
105
|
+
new_stub(:head, path, headers, &block)
|
106
|
+
end
|
107
|
+
|
108
|
+
def post(path, body = nil, headers = {}, &block)
|
109
|
+
new_stub(:post, path, headers, body, &block)
|
110
|
+
end
|
111
|
+
|
112
|
+
def put(path, body = nil, headers = {}, &block)
|
113
|
+
new_stub(:put, path, headers, body, &block)
|
114
|
+
end
|
115
|
+
|
116
|
+
def patch(path, body = nil, headers = {}, &block)
|
117
|
+
new_stub(:patch, path, headers, body, &block)
|
118
|
+
end
|
119
|
+
|
120
|
+
def delete(path, headers = {}, &block)
|
121
|
+
new_stub(:delete, path, headers, &block)
|
122
|
+
end
|
123
|
+
|
124
|
+
def options(path, headers = {}, &block)
|
125
|
+
new_stub(:options, path, headers, &block)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Raises an error if any of the stubbed calls have not been made.
|
129
|
+
def verify_stubbed_calls
|
130
|
+
failed_stubs = []
|
131
|
+
@stack.each do |method, stubs|
|
132
|
+
next if stubs.empty?
|
133
|
+
|
134
|
+
failed_stubs.concat(
|
135
|
+
stubs.map do |stub|
|
136
|
+
"Expected #{method} #{stub}."
|
137
|
+
end
|
138
|
+
)
|
139
|
+
end
|
140
|
+
raise failed_stubs.join(' ') unless failed_stubs.empty?
|
141
|
+
end
|
142
|
+
|
143
|
+
# Set strict_mode. If the value is true, this adapter tries to find matched requests strictly,
|
144
|
+
# which means that all of a path, parameters, and headers must be the same as an actual request.
|
145
|
+
def strict_mode=(value)
|
146
|
+
@strict_mode = value
|
147
|
+
@stack.each do |_method, stubs|
|
148
|
+
stubs.each do |stub|
|
149
|
+
stub.strict_mode = value
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
protected
|
155
|
+
|
156
|
+
def new_stub(request_method, path, headers = {}, body = nil, &block)
|
157
|
+
normalized_path, host =
|
158
|
+
if path.is_a?(Regexp)
|
159
|
+
path
|
160
|
+
else
|
161
|
+
[
|
162
|
+
Faraday::Utils.normalize_path(path),
|
163
|
+
Faraday::Utils.URI(path).host
|
164
|
+
]
|
165
|
+
end
|
166
|
+
path, query = normalized_path.respond_to?(:split) ? normalized_path.split('?') : normalized_path
|
167
|
+
headers = Utils::Headers.new(headers)
|
168
|
+
|
169
|
+
stub = Stub.new(host, path, query, headers, body, @strict_mode, block)
|
170
|
+
(@stack[request_method] ||= []) << stub
|
171
|
+
end
|
172
|
+
|
173
|
+
# @param stack [Hash]
|
174
|
+
# @param env [Faraday::Env]
|
175
|
+
def matches?(stack, env)
|
176
|
+
stack.each do |stub|
|
177
|
+
match_result, meta = stub.matches?(env)
|
178
|
+
return stub, meta if match_result
|
179
|
+
end
|
180
|
+
nil
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# Stub request
|
185
|
+
class Stub < Struct.new(:host, :path, :query, :headers, :body, :strict_mode, :block) # rubocop:disable Style/StructInheritance
|
186
|
+
# @param env [Faraday::Env]
|
187
|
+
def matches?(env)
|
188
|
+
request_host = env[:url].host
|
189
|
+
request_path = Faraday::Utils.normalize_path(env[:url].path)
|
190
|
+
request_headers = env.request_headers
|
191
|
+
request_body = env[:body]
|
192
|
+
|
193
|
+
# meta is a hash used as carrier
|
194
|
+
# that will be yielded to consumer block
|
195
|
+
meta = {}
|
196
|
+
[(host.nil? || host == request_host) &&
|
197
|
+
path_match?(request_path, meta) &&
|
198
|
+
params_match?(env) &&
|
199
|
+
body_match?(request_body) &&
|
200
|
+
headers_match?(request_headers), meta]
|
201
|
+
end
|
202
|
+
|
203
|
+
def path_match?(request_path, meta)
|
204
|
+
if path.is_a?(Regexp)
|
205
|
+
!!(meta[:match_data] = path.match(request_path))
|
206
|
+
else
|
207
|
+
path == request_path
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# @param env [Faraday::Env]
|
212
|
+
def params_match?(env)
|
213
|
+
request_params = env[:params]
|
214
|
+
params = env.params_encoder.decode(query) || {}
|
215
|
+
|
216
|
+
if strict_mode
|
217
|
+
return Set.new(params) == Set.new(request_params)
|
218
|
+
end
|
219
|
+
|
220
|
+
params.keys.all? do |key|
|
221
|
+
request_params[key] == params[key]
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def headers_match?(request_headers)
|
226
|
+
if strict_mode
|
227
|
+
headers_with_user_agent = headers.dup.tap do |hs|
|
228
|
+
# NOTE: Set User-Agent in case it's not set when creating Stubs.
|
229
|
+
# Users would not want to set Faraday's User-Agent explicitly.
|
230
|
+
hs[:user_agent] ||= Connection::USER_AGENT
|
231
|
+
end
|
232
|
+
return Set.new(headers_with_user_agent) == Set.new(request_headers)
|
233
|
+
end
|
234
|
+
|
235
|
+
headers.keys.all? do |key|
|
236
|
+
request_headers[key] == headers[key]
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def body_match?(request_body)
|
241
|
+
return true if body.to_s.size.zero?
|
242
|
+
|
243
|
+
case body
|
244
|
+
when Proc
|
245
|
+
body.call(request_body)
|
246
|
+
else
|
247
|
+
request_body == body
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
def to_s
|
252
|
+
"#{path} #{body}"
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
def initialize(app, stubs = nil, &block)
|
257
|
+
super(app)
|
258
|
+
@stubs = stubs || Stubs.new
|
259
|
+
configure(&block) if block
|
260
|
+
end
|
261
|
+
|
262
|
+
def configure
|
263
|
+
yield(stubs)
|
264
|
+
end
|
265
|
+
|
266
|
+
# @param env [Faraday::Env]
|
267
|
+
def call(env)
|
268
|
+
super
|
269
|
+
|
270
|
+
env.request.params_encoder ||= Faraday::Utils.default_params_encoder
|
271
|
+
env[:params] = env.params_encoder.decode(env[:url].query) || {}
|
272
|
+
stub, meta = stubs.match(env)
|
273
|
+
|
274
|
+
unless stub
|
275
|
+
raise Stubs::NotFound, "no stubbed request for #{env[:method]} " \
|
276
|
+
"#{env[:url]} #{env[:body]}"
|
277
|
+
end
|
278
|
+
|
279
|
+
block_arity = stub.block.arity
|
280
|
+
status, headers, body =
|
281
|
+
if block_arity >= 0
|
282
|
+
stub.block.call(*[env, meta].take(block_arity))
|
283
|
+
else
|
284
|
+
stub.block.call(env, meta)
|
285
|
+
end
|
286
|
+
|
287
|
+
# We need to explicitly pass `reason_phrase = nil` here to avoid keyword args conflicts.
|
288
|
+
# See https://github.com/lostisland/faraday/issues/1444
|
289
|
+
# TODO: remove `nil` explicit reason_phrase once Ruby 3.0 becomes minimum req. version
|
290
|
+
save_response(env, status, body, headers, nil)
|
291
|
+
|
292
|
+
@app.call(env)
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
Faraday::Adapter.register_middleware(test: Faraday::Adapter::Test)
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Faraday
|
4
|
+
# Base class for all Faraday adapters. Adapters are
|
5
|
+
# responsible for fulfilling a Faraday request.
|
6
|
+
class Adapter
|
7
|
+
extend MiddlewareRegistry
|
8
|
+
|
9
|
+
CONTENT_LENGTH = 'Content-Length'
|
10
|
+
|
11
|
+
# This module marks an Adapter as supporting parallel requests.
|
12
|
+
module Parallelism
|
13
|
+
attr_writer :supports_parallel
|
14
|
+
|
15
|
+
def supports_parallel?
|
16
|
+
@supports_parallel
|
17
|
+
end
|
18
|
+
|
19
|
+
def inherited(subclass)
|
20
|
+
super
|
21
|
+
subclass.supports_parallel = supports_parallel?
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
extend Parallelism
|
26
|
+
self.supports_parallel = false
|
27
|
+
|
28
|
+
def initialize(_app = nil, opts = {}, &block)
|
29
|
+
@app = ->(env) { env.response }
|
30
|
+
@connection_options = opts
|
31
|
+
@config_block = block
|
32
|
+
end
|
33
|
+
|
34
|
+
# Yields or returns an adapter's configured connection. Depends on
|
35
|
+
# #build_connection being defined on this adapter.
|
36
|
+
#
|
37
|
+
# @param env [Faraday::Env, Hash] The env object for a faraday request.
|
38
|
+
#
|
39
|
+
# @return The return value of the given block, or the HTTP connection object
|
40
|
+
# if no block is given.
|
41
|
+
def connection(env)
|
42
|
+
conn = build_connection(env)
|
43
|
+
return conn unless block_given?
|
44
|
+
|
45
|
+
yield conn
|
46
|
+
end
|
47
|
+
|
48
|
+
# Close any persistent connections. The adapter should still be usable
|
49
|
+
# after calling close.
|
50
|
+
def close
|
51
|
+
# Possible implementation:
|
52
|
+
# @app.close if @app.respond_to?(:close)
|
53
|
+
end
|
54
|
+
|
55
|
+
def call(env)
|
56
|
+
env.clear_body if env.needs_body?
|
57
|
+
env.response = Response.new
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def save_response(env, status, body, headers = nil, reason_phrase = nil, finished: true)
|
63
|
+
env.status = status
|
64
|
+
env.body = body
|
65
|
+
env.reason_phrase = reason_phrase&.to_s&.strip
|
66
|
+
env.response_headers = Utils::Headers.new.tap do |response_headers|
|
67
|
+
response_headers.update headers unless headers.nil?
|
68
|
+
yield(response_headers) if block_given?
|
69
|
+
end
|
70
|
+
|
71
|
+
env.response.finish(env) unless env.parallel? || !finished
|
72
|
+
env.response
|
73
|
+
end
|
74
|
+
|
75
|
+
# Fetches either a read, write, or open timeout setting. Defaults to the
|
76
|
+
# :timeout value if a more specific one is not given.
|
77
|
+
#
|
78
|
+
# @param type [Symbol] Describes which timeout setting to get: :read,
|
79
|
+
# :write, or :open.
|
80
|
+
# @param options [Hash] Hash containing Symbol keys like :timeout,
|
81
|
+
# :read_timeout, :write_timeout, :open_timeout, or
|
82
|
+
# :timeout
|
83
|
+
#
|
84
|
+
# @return [Integer, nil] Timeout duration in seconds, or nil if no timeout
|
85
|
+
# has been set.
|
86
|
+
def request_timeout(type, options)
|
87
|
+
key = TIMEOUT_KEYS.fetch(type) do
|
88
|
+
msg = "Expected :read, :write, :open. Got #{type.inspect} :("
|
89
|
+
raise ArgumentError, msg
|
90
|
+
end
|
91
|
+
options[key] || options[:timeout]
|
92
|
+
end
|
93
|
+
|
94
|
+
TIMEOUT_KEYS = {
|
95
|
+
read: :read_timeout,
|
96
|
+
open: :open_timeout,
|
97
|
+
write: :write_timeout
|
98
|
+
}.freeze
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
require 'faraday/adapter/test'
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'monitor'
|
4
|
+
|
5
|
+
module Faraday
|
6
|
+
# AdapterRegistry registers adapter class names so they can be looked up by a
|
7
|
+
# String or Symbol name.
|
8
|
+
class AdapterRegistry
|
9
|
+
def initialize
|
10
|
+
@lock = Monitor.new
|
11
|
+
@constants = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def get(name)
|
15
|
+
klass = @lock.synchronize do
|
16
|
+
@constants[name]
|
17
|
+
end
|
18
|
+
return klass if klass
|
19
|
+
|
20
|
+
Object.const_get(name).tap { |c| set(c, name) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def set(klass, name = nil)
|
24
|
+
name ||= klass.to_s
|
25
|
+
@lock.synchronize do
|
26
|
+
@constants[name] = klass
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|