nano-sharp-sys 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/faraday-2.14.3/CHANGELOG.md +574 -0
  3. data/faraday-2.14.3/LICENSE.md +20 -0
  4. data/faraday-2.14.3/README.md +67 -0
  5. data/faraday-2.14.3/Rakefile +12 -0
  6. data/faraday-2.14.3/examples/client_spec.rb +119 -0
  7. data/faraday-2.14.3/examples/client_test.rb +144 -0
  8. data/faraday-2.14.3/lib/faraday/adapter/test.rb +319 -0
  9. data/faraday-2.14.3/lib/faraday/adapter.rb +102 -0
  10. data/faraday-2.14.3/lib/faraday/adapter_registry.rb +30 -0
  11. data/faraday-2.14.3/lib/faraday/connection.rb +567 -0
  12. data/faraday-2.14.3/lib/faraday/encoders/flat_params_encoder.rb +106 -0
  13. data/faraday-2.14.3/lib/faraday/encoders/nested_params_encoder.rb +193 -0
  14. data/faraday-2.14.3/lib/faraday/error.rb +202 -0
  15. data/faraday-2.14.3/lib/faraday/logging/formatter.rb +118 -0
  16. data/faraday-2.14.3/lib/faraday/methods.rb +6 -0
  17. data/faraday-2.14.3/lib/faraday/middleware.rb +72 -0
  18. data/faraday-2.14.3/lib/faraday/middleware_registry.rb +83 -0
  19. data/faraday-2.14.3/lib/faraday/options/connection_options.rb +23 -0
  20. data/faraday-2.14.3/lib/faraday/options/env.rb +204 -0
  21. data/faraday-2.14.3/lib/faraday/options/proxy_options.rb +39 -0
  22. data/faraday-2.14.3/lib/faraday/options/request_options.rb +23 -0
  23. data/faraday-2.14.3/lib/faraday/options/ssl_options.rb +76 -0
  24. data/faraday-2.14.3/lib/faraday/options.rb +219 -0
  25. data/faraday-2.14.3/lib/faraday/parameters.rb +5 -0
  26. data/faraday-2.14.3/lib/faraday/rack_builder.rb +248 -0
  27. data/faraday-2.14.3/lib/faraday/request/authorization.rb +54 -0
  28. data/faraday-2.14.3/lib/faraday/request/instrumentation.rb +58 -0
  29. data/faraday-2.14.3/lib/faraday/request/json.rb +70 -0
  30. data/faraday-2.14.3/lib/faraday/request/url_encoded.rb +60 -0
  31. data/faraday-2.14.3/lib/faraday/request.rb +139 -0
  32. data/faraday-2.14.3/lib/faraday/response/json.rb +74 -0
  33. data/faraday-2.14.3/lib/faraday/response/logger.rb +39 -0
  34. data/faraday-2.14.3/lib/faraday/response/raise_error.rb +83 -0
  35. data/faraday-2.14.3/lib/faraday/response.rb +95 -0
  36. data/faraday-2.14.3/lib/faraday/utils/headers.rb +150 -0
  37. data/faraday-2.14.3/lib/faraday/utils/params_hash.rb +61 -0
  38. data/faraday-2.14.3/lib/faraday/utils.rb +121 -0
  39. data/faraday-2.14.3/lib/faraday/version.rb +5 -0
  40. data/faraday-2.14.3/lib/faraday.rb +158 -0
  41. data/faraday-2.14.3/spec/external_adapters/faraday_specs_setup.rb +14 -0
  42. data/faraday-2.14.3/spec/faraday/adapter/test_spec.rb +460 -0
  43. data/faraday-2.14.3/spec/faraday/adapter_registry_spec.rb +28 -0
  44. data/faraday-2.14.3/spec/faraday/adapter_spec.rb +55 -0
  45. data/faraday-2.14.3/spec/faraday/connection_spec.rb +860 -0
  46. data/faraday-2.14.3/spec/faraday/error_spec.rb +175 -0
  47. data/faraday-2.14.3/spec/faraday/middleware_registry_spec.rb +31 -0
  48. data/faraday-2.14.3/spec/faraday/middleware_spec.rb +213 -0
  49. data/faraday-2.14.3/spec/faraday/options/env_spec.rb +76 -0
  50. data/faraday-2.14.3/spec/faraday/options/options_spec.rb +297 -0
  51. data/faraday-2.14.3/spec/faraday/options/proxy_options_spec.rb +79 -0
  52. data/faraday-2.14.3/spec/faraday/options/request_options_spec.rb +19 -0
  53. data/faraday-2.14.3/spec/faraday/params_encoders/flat_spec.rb +42 -0
  54. data/faraday-2.14.3/spec/faraday/params_encoders/nested_spec.rb +179 -0
  55. data/faraday-2.14.3/spec/faraday/rack_builder_spec.rb +317 -0
  56. data/faraday-2.14.3/spec/faraday/request/authorization_spec.rb +118 -0
  57. data/faraday-2.14.3/spec/faraday/request/instrumentation_spec.rb +74 -0
  58. data/faraday-2.14.3/spec/faraday/request/json_spec.rb +199 -0
  59. data/faraday-2.14.3/spec/faraday/request/url_encoded_spec.rb +93 -0
  60. data/faraday-2.14.3/spec/faraday/request_spec.rb +119 -0
  61. data/faraday-2.14.3/spec/faraday/response/json_spec.rb +206 -0
  62. data/faraday-2.14.3/spec/faraday/response/logger_spec.rb +299 -0
  63. data/faraday-2.14.3/spec/faraday/response/raise_error_spec.rb +286 -0
  64. data/faraday-2.14.3/spec/faraday/response_spec.rb +84 -0
  65. data/faraday-2.14.3/spec/faraday/utils/headers_spec.rb +109 -0
  66. data/faraday-2.14.3/spec/faraday/utils_spec.rb +120 -0
  67. data/faraday-2.14.3/spec/faraday_spec.rb +43 -0
  68. data/faraday-2.14.3/spec/spec_helper.rb +133 -0
  69. data/faraday-2.14.3/spec/support/disabling_stub.rb +14 -0
  70. data/faraday-2.14.3/spec/support/fake_safe_buffer.rb +15 -0
  71. data/faraday-2.14.3/spec/support/faraday_middleware_subclasses.rb +18 -0
  72. data/faraday-2.14.3/spec/support/helper_methods.rb +96 -0
  73. data/faraday-2.14.3/spec/support/shared_examples/adapter.rb +105 -0
  74. data/faraday-2.14.3/spec/support/shared_examples/params_encoder.rb +18 -0
  75. data/faraday-2.14.3/spec/support/shared_examples/request_method.rb +263 -0
  76. data/faraday-2.14.3/spec/support/streaming_response_checker.rb +35 -0
  77. data/nano-sharp-sys.gemspec +12 -0
  78. metadata +117 -0
@@ -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 # rubocop:disable Style/OneClassPerFile
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,319 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'timeout'
4
+
5
+ module Faraday
6
+ class Adapter
7
+ # @example
8
+ # test = Faraday::Connection.new do
9
+ # use Faraday::Adapter::Test do |stub|
10
+ # # Define matcher to match the request
11
+ # stub.get '/resource.json' do
12
+ # # return static content
13
+ # [200, {'Content-Type' => 'application/json'}, 'hi world']
14
+ # end
15
+ #
16
+ # # response with content generated based on request
17
+ # stub.get '/showget' do |env|
18
+ # [200, {'Content-Type' => 'text/plain'}, env[:method].to_s]
19
+ # end
20
+ #
21
+ # # A regular expression can be used as matching filter
22
+ # stub.get /\A\/items\/(\d+)\z/ do |env, meta|
23
+ # # in case regular expression is used, an instance of MatchData
24
+ # # can be received
25
+ # [200,
26
+ # {'Content-Type' => 'text/plain'},
27
+ # "showing item: #{meta[:match_data][1]}"
28
+ # ]
29
+ # end
30
+ #
31
+ # # Test the request body is the same as the stubbed body
32
+ # stub.post('/bar', 'name=YK&word=call') { [200, {}, ''] }
33
+ #
34
+ # # You can pass a proc as a stubbed body and check the request body in your way.
35
+ # # In this case, the proc should return true or false.
36
+ # stub.post('/foo', ->(request_body) do
37
+ # JSON.parse(request_body).slice('name') == { 'name' => 'YK' } }) { [200, {}, '']
38
+ # end
39
+ #
40
+ # # You can set strict_mode to exactly match the stubbed requests.
41
+ # stub.strict_mode = true
42
+ # end
43
+ # end
44
+ #
45
+ # resp = test.get '/resource.json'
46
+ # resp.body # => 'hi world'
47
+ #
48
+ # resp = test.get '/showget'
49
+ # resp.body # => 'get'
50
+ #
51
+ # resp = test.get '/items/1'
52
+ # resp.body # => 'showing item: 1'
53
+ #
54
+ # resp = test.get '/items/2'
55
+ # resp.body # => 'showing item: 2'
56
+ #
57
+ # resp = test.post '/bar', 'name=YK&word=call'
58
+ # resp.status # => 200
59
+ #
60
+ # resp = test.post '/foo', JSON.dump(name: 'YK', created_at: Time.now)
61
+ # resp.status # => 200
62
+ class Test < Faraday::Adapter
63
+ attr_accessor :stubs
64
+
65
+ # A stack of Stubs
66
+ class Stubs
67
+ class NotFound < StandardError
68
+ end
69
+
70
+ def initialize(strict_mode: false)
71
+ # { get: [Stub, Stub] }
72
+ @stack = {}
73
+ @consumed = {}
74
+ @strict_mode = strict_mode
75
+ @stubs_mutex = Monitor.new
76
+ yield(self) if block_given?
77
+ end
78
+
79
+ def empty?
80
+ @stack.empty?
81
+ end
82
+
83
+ # @param env [Faraday::Env]
84
+ def match(env)
85
+ request_method = env[:method]
86
+ return false unless @stack.key?(request_method)
87
+
88
+ stack = @stack[request_method]
89
+ consumed = (@consumed[request_method] ||= [])
90
+
91
+ @stubs_mutex.synchronize do
92
+ stub, meta = matches?(stack, env)
93
+ if stub
94
+ removed = stack.delete(stub)
95
+ consumed << removed unless removed.nil?
96
+ return stub, meta
97
+ end
98
+ end
99
+ matches?(consumed, env)
100
+ end
101
+
102
+ def get(path, headers = {}, &block)
103
+ new_stub(:get, path, headers, &block)
104
+ end
105
+
106
+ def head(path, headers = {}, &block)
107
+ new_stub(:head, path, headers, &block)
108
+ end
109
+
110
+ def post(path, body = nil, headers = {}, &block)
111
+ new_stub(:post, path, headers, body, &block)
112
+ end
113
+
114
+ def put(path, body = nil, headers = {}, &block)
115
+ new_stub(:put, path, headers, body, &block)
116
+ end
117
+
118
+ def patch(path, body = nil, headers = {}, &block)
119
+ new_stub(:patch, path, headers, body, &block)
120
+ end
121
+
122
+ def delete(path, headers = {}, &block)
123
+ new_stub(:delete, path, headers, &block)
124
+ end
125
+
126
+ def options(path, headers = {}, &block)
127
+ new_stub(:options, path, headers, &block)
128
+ end
129
+
130
+ # Removes all stubs, including the ones that have already been consumed.
131
+ def clear
132
+ @stubs_mutex.synchronize do
133
+ @stack.clear
134
+ @consumed.clear
135
+ end
136
+ end
137
+
138
+ # Raises an error if any of the stubbed calls have not been made.
139
+ def verify_stubbed_calls
140
+ failed_stubs = []
141
+ @stack.each do |method, stubs|
142
+ next if stubs.empty?
143
+
144
+ failed_stubs.concat(
145
+ stubs.map do |stub|
146
+ "Expected #{method} #{stub}."
147
+ end
148
+ )
149
+ end
150
+ raise failed_stubs.join(' ') unless failed_stubs.empty?
151
+ end
152
+
153
+ # Set strict_mode. If the value is true, this adapter tries to find matched requests strictly,
154
+ # which means that all of a path, parameters, and headers must be the same as an actual request.
155
+ def strict_mode=(value)
156
+ @strict_mode = value
157
+ @stack.each_value do |stubs|
158
+ stubs.each do |stub|
159
+ stub.strict_mode = value
160
+ end
161
+ end
162
+ end
163
+
164
+ protected
165
+
166
+ def new_stub(request_method, path, headers = {}, body = nil, &block)
167
+ normalized_path, host =
168
+ if path.is_a?(Regexp)
169
+ path
170
+ else
171
+ [
172
+ Faraday::Utils.normalize_path(path),
173
+ Faraday::Utils.URI(path).host
174
+ ]
175
+ end
176
+ path, query = normalized_path.respond_to?(:split) ? normalized_path.split('?') : normalized_path
177
+ headers = Utils::Headers.new(headers)
178
+
179
+ stub = Stub.new(host, path, query, headers, body, @strict_mode, block)
180
+ (@stack[request_method] ||= []) << stub
181
+ end
182
+
183
+ # @param stack [Hash]
184
+ # @param env [Faraday::Env]
185
+ def matches?(stack, env)
186
+ stack.each do |stub|
187
+ match_result, meta = stub.matches?(env)
188
+ return stub, meta if match_result
189
+ end
190
+ nil
191
+ end
192
+ end
193
+
194
+ # Stub request
195
+ Stub = Struct.new(:host, :path, :query, :headers, :body, :strict_mode, :block) do
196
+ # @param env [Faraday::Env]
197
+ def matches?(env)
198
+ request_host = env[:url].host
199
+ request_path = Faraday::Utils.normalize_path(env[:url].path)
200
+ request_headers = env.request_headers
201
+ request_body = env[:body]
202
+
203
+ # meta is a hash used as carrier
204
+ # that will be yielded to consumer block
205
+ meta = {}
206
+ [(host.nil? || host == request_host) &&
207
+ path_match?(request_path, meta) &&
208
+ params_match?(env) &&
209
+ body_match?(request_body) &&
210
+ headers_match?(request_headers), meta]
211
+ end
212
+
213
+ def path_match?(request_path, meta)
214
+ if path.is_a?(Regexp)
215
+ !!(meta[:match_data] = path.match(request_path))
216
+ else
217
+ path == request_path
218
+ end
219
+ end
220
+
221
+ # @param env [Faraday::Env]
222
+ def params_match?(env)
223
+ request_params = env[:params]
224
+ params = env.params_encoder.decode(query) || {}
225
+
226
+ if strict_mode
227
+ return Set.new(params) == Set.new(request_params)
228
+ end
229
+
230
+ params.keys.all? do |key|
231
+ request_params[key] == params[key]
232
+ end
233
+ end
234
+
235
+ def headers_match?(request_headers)
236
+ if strict_mode
237
+ headers_with_user_agent = headers.dup.tap do |hs|
238
+ # NOTE: Set User-Agent in case it's not set when creating Stubs.
239
+ # Users would not want to set Faraday's User-Agent explicitly.
240
+ hs[:user_agent] ||= Connection::USER_AGENT
241
+ end
242
+ return Set.new(headers_with_user_agent) == Set.new(request_headers)
243
+ end
244
+
245
+ headers.keys.all? do |key|
246
+ request_headers[key] == headers[key]
247
+ end
248
+ end
249
+
250
+ def body_match?(request_body)
251
+ return true if body.to_s.empty?
252
+
253
+ case body
254
+ when Proc
255
+ body.call(request_body)
256
+ else
257
+ request_body == body
258
+ end
259
+ end
260
+
261
+ def to_s
262
+ "#{path} #{body}"
263
+ end
264
+ end
265
+
266
+ def initialize(app, stubs = nil, &block)
267
+ super(app)
268
+ @stubs = stubs || Stubs.new
269
+ configure(&block) if block
270
+ end
271
+
272
+ def configure
273
+ yield(stubs)
274
+ end
275
+
276
+ # @param env [Faraday::Env]
277
+ def call(env)
278
+ super
279
+
280
+ env.request.params_encoder ||= Faraday::Utils.default_params_encoder
281
+ env[:params] = env.params_encoder.decode(env[:url].query) || {}
282
+ stub, meta = stubs.match(env)
283
+
284
+ unless stub
285
+ raise Stubs::NotFound, "no stubbed request for #{env[:method]} " \
286
+ "#{env[:url]} #{env[:body]} #{env[:headers]}"
287
+ end
288
+
289
+ block_arity = stub.block.arity
290
+ params = if block_arity >= 0
291
+ [env, meta].take(block_arity)
292
+ else
293
+ [env, meta]
294
+ end
295
+
296
+ timeout = request_timeout(:open, env[:request])
297
+ timeout ||= request_timeout(:read, env[:request])
298
+
299
+ status, headers, body =
300
+ if timeout
301
+ ::Timeout.timeout(timeout, Faraday::TimeoutError) do
302
+ stub.block.call(*params)
303
+ end
304
+ else
305
+ stub.block.call(*params)
306
+ end
307
+
308
+ # We need to explicitly pass `reason_phrase = nil` here to avoid keyword args conflicts.
309
+ # See https://github.com/lostisland/faraday/issues/1444
310
+ # TODO: remove `nil` explicit reason_phrase once Ruby 3.0 becomes minimum req. version
311
+ save_response(env, status, body, headers, nil)
312
+
313
+ @app.call(env)
314
+ end
315
+ end
316
+ end
317
+ end
318
+
319
+ 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
+ TIMEOUT_KEYS = {
12
+ read: :read_timeout,
13
+ open: :open_timeout,
14
+ write: :write_timeout
15
+ }.freeze
16
+
17
+ # This module marks an Adapter as supporting parallel requests.
18
+ module Parallelism
19
+ attr_writer :supports_parallel
20
+
21
+ def supports_parallel?
22
+ @supports_parallel
23
+ end
24
+
25
+ def inherited(subclass)
26
+ super
27
+ subclass.supports_parallel = supports_parallel?
28
+ end
29
+ end
30
+
31
+ extend Parallelism
32
+
33
+ self.supports_parallel = false
34
+
35
+ def initialize(_app = nil, opts = {}, &block)
36
+ @app = lambda(&:response)
37
+ @connection_options = opts
38
+ @config_block = block
39
+ end
40
+
41
+ # Yields or returns an adapter's configured connection. Depends on
42
+ # #build_connection being defined on this adapter.
43
+ #
44
+ # @param env [Faraday::Env, Hash] The env object for a faraday request.
45
+ #
46
+ # @return The return value of the given block, or the HTTP connection object
47
+ # if no block is given.
48
+ def connection(env)
49
+ conn = build_connection(env)
50
+ return conn unless block_given?
51
+
52
+ yield conn
53
+ end
54
+
55
+ # Close any persistent connections. The adapter should still be usable
56
+ # after calling close.
57
+ def close
58
+ # Possible implementation:
59
+ # @app.close if @app.respond_to?(:close)
60
+ end
61
+
62
+ def call(env)
63
+ env.clear_body if env.needs_body?
64
+ env.response = Response.new
65
+ end
66
+
67
+ private
68
+
69
+ def save_response(env, status, body, headers = nil, reason_phrase = nil, finished: true)
70
+ env.status = status
71
+ env.body = body
72
+ env.reason_phrase = reason_phrase&.to_s&.strip
73
+ env.response_headers = Utils::Headers.new.tap do |response_headers|
74
+ response_headers.update headers unless headers.nil?
75
+ yield(response_headers) if block_given?
76
+ end
77
+
78
+ env.response.finish(env) unless env.parallel? || !finished
79
+ env.response
80
+ end
81
+
82
+ # Fetches either a read, write, or open timeout setting. Defaults to the
83
+ # :timeout value if a more specific one is not given.
84
+ #
85
+ # @param type [Symbol] Describes which timeout setting to get: :read,
86
+ # :write, or :open.
87
+ # @param options [Hash] Hash containing Symbol keys like :timeout,
88
+ # :read_timeout, :write_timeout, or :open_timeout
89
+ #
90
+ # @return [Integer, nil] Timeout duration in seconds, or nil if no timeout
91
+ # has been set.
92
+ def request_timeout(type, options)
93
+ key = TIMEOUT_KEYS.fetch(type) do
94
+ msg = "Expected :read, :write, :open. Got #{type.inspect} :("
95
+ raise ArgumentError, msg
96
+ end
97
+ options[key] || options[:timeout]
98
+ end
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