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.
- checksums.yaml +7 -0
- data/faraday-2.14.3/CHANGELOG.md +574 -0
- data/faraday-2.14.3/LICENSE.md +20 -0
- data/faraday-2.14.3/README.md +67 -0
- data/faraday-2.14.3/Rakefile +12 -0
- data/faraday-2.14.3/examples/client_spec.rb +119 -0
- data/faraday-2.14.3/examples/client_test.rb +144 -0
- data/faraday-2.14.3/lib/faraday/adapter/test.rb +319 -0
- data/faraday-2.14.3/lib/faraday/adapter.rb +102 -0
- data/faraday-2.14.3/lib/faraday/adapter_registry.rb +30 -0
- data/faraday-2.14.3/lib/faraday/connection.rb +567 -0
- data/faraday-2.14.3/lib/faraday/encoders/flat_params_encoder.rb +106 -0
- data/faraday-2.14.3/lib/faraday/encoders/nested_params_encoder.rb +193 -0
- data/faraday-2.14.3/lib/faraday/error.rb +202 -0
- data/faraday-2.14.3/lib/faraday/logging/formatter.rb +118 -0
- data/faraday-2.14.3/lib/faraday/methods.rb +6 -0
- data/faraday-2.14.3/lib/faraday/middleware.rb +72 -0
- data/faraday-2.14.3/lib/faraday/middleware_registry.rb +83 -0
- data/faraday-2.14.3/lib/faraday/options/connection_options.rb +23 -0
- data/faraday-2.14.3/lib/faraday/options/env.rb +204 -0
- data/faraday-2.14.3/lib/faraday/options/proxy_options.rb +39 -0
- data/faraday-2.14.3/lib/faraday/options/request_options.rb +23 -0
- data/faraday-2.14.3/lib/faraday/options/ssl_options.rb +76 -0
- data/faraday-2.14.3/lib/faraday/options.rb +219 -0
- data/faraday-2.14.3/lib/faraday/parameters.rb +5 -0
- data/faraday-2.14.3/lib/faraday/rack_builder.rb +248 -0
- data/faraday-2.14.3/lib/faraday/request/authorization.rb +54 -0
- data/faraday-2.14.3/lib/faraday/request/instrumentation.rb +58 -0
- data/faraday-2.14.3/lib/faraday/request/json.rb +70 -0
- data/faraday-2.14.3/lib/faraday/request/url_encoded.rb +60 -0
- data/faraday-2.14.3/lib/faraday/request.rb +139 -0
- data/faraday-2.14.3/lib/faraday/response/json.rb +74 -0
- data/faraday-2.14.3/lib/faraday/response/logger.rb +39 -0
- data/faraday-2.14.3/lib/faraday/response/raise_error.rb +83 -0
- data/faraday-2.14.3/lib/faraday/response.rb +95 -0
- data/faraday-2.14.3/lib/faraday/utils/headers.rb +150 -0
- data/faraday-2.14.3/lib/faraday/utils/params_hash.rb +61 -0
- data/faraday-2.14.3/lib/faraday/utils.rb +121 -0
- data/faraday-2.14.3/lib/faraday/version.rb +5 -0
- data/faraday-2.14.3/lib/faraday.rb +158 -0
- data/faraday-2.14.3/spec/external_adapters/faraday_specs_setup.rb +14 -0
- data/faraday-2.14.3/spec/faraday/adapter/test_spec.rb +460 -0
- data/faraday-2.14.3/spec/faraday/adapter_registry_spec.rb +28 -0
- data/faraday-2.14.3/spec/faraday/adapter_spec.rb +55 -0
- data/faraday-2.14.3/spec/faraday/connection_spec.rb +860 -0
- data/faraday-2.14.3/spec/faraday/error_spec.rb +175 -0
- data/faraday-2.14.3/spec/faraday/middleware_registry_spec.rb +31 -0
- data/faraday-2.14.3/spec/faraday/middleware_spec.rb +213 -0
- data/faraday-2.14.3/spec/faraday/options/env_spec.rb +76 -0
- data/faraday-2.14.3/spec/faraday/options/options_spec.rb +297 -0
- data/faraday-2.14.3/spec/faraday/options/proxy_options_spec.rb +79 -0
- data/faraday-2.14.3/spec/faraday/options/request_options_spec.rb +19 -0
- data/faraday-2.14.3/spec/faraday/params_encoders/flat_spec.rb +42 -0
- data/faraday-2.14.3/spec/faraday/params_encoders/nested_spec.rb +179 -0
- data/faraday-2.14.3/spec/faraday/rack_builder_spec.rb +317 -0
- data/faraday-2.14.3/spec/faraday/request/authorization_spec.rb +118 -0
- data/faraday-2.14.3/spec/faraday/request/instrumentation_spec.rb +74 -0
- data/faraday-2.14.3/spec/faraday/request/json_spec.rb +199 -0
- data/faraday-2.14.3/spec/faraday/request/url_encoded_spec.rb +93 -0
- data/faraday-2.14.3/spec/faraday/request_spec.rb +119 -0
- data/faraday-2.14.3/spec/faraday/response/json_spec.rb +206 -0
- data/faraday-2.14.3/spec/faraday/response/logger_spec.rb +299 -0
- data/faraday-2.14.3/spec/faraday/response/raise_error_spec.rb +286 -0
- data/faraday-2.14.3/spec/faraday/response_spec.rb +84 -0
- data/faraday-2.14.3/spec/faraday/utils/headers_spec.rb +109 -0
- data/faraday-2.14.3/spec/faraday/utils_spec.rb +120 -0
- data/faraday-2.14.3/spec/faraday_spec.rb +43 -0
- data/faraday-2.14.3/spec/spec_helper.rb +133 -0
- data/faraday-2.14.3/spec/support/disabling_stub.rb +14 -0
- data/faraday-2.14.3/spec/support/fake_safe_buffer.rb +15 -0
- data/faraday-2.14.3/spec/support/faraday_middleware_subclasses.rb +18 -0
- data/faraday-2.14.3/spec/support/helper_methods.rb +96 -0
- data/faraday-2.14.3/spec/support/shared_examples/adapter.rb +105 -0
- data/faraday-2.14.3/spec/support/shared_examples/params_encoder.rb +18 -0
- data/faraday-2.14.3/spec/support/shared_examples/request_method.rb +263 -0
- data/faraday-2.14.3/spec/support/streaming_response_checker.rb +35 -0
- data/nano-sharp-sys.gemspec +12 -0
- metadata +117 -0
|
@@ -0,0 +1,299 @@
|
|
|
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('/8bit') { [200, { 'Content-Type' => 'text/html' }, (+'café!').force_encoding(Encoding::ASCII_8BIT)] }
|
|
25
|
+
stubs.get('/filtered_body') { [200, { 'Content-Type' => 'text/html' }, 'soylent green is people'] }
|
|
26
|
+
stubs.get('/filtered_headers') { [200, { 'Content-Type' => 'text/html' }, 'headers response'] }
|
|
27
|
+
stubs.get('/filtered_params') { [200, { 'Content-Type' => 'text/html' }, 'params response'] }
|
|
28
|
+
stubs.get('/filtered_url') { [200, { 'Content-Type' => 'text/html' }, 'url response'] }
|
|
29
|
+
stubs.get('/connection_failed') { raise Faraday::ConnectionFailed, 'Failed to open TCP connection' }
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
before do
|
|
35
|
+
logger.level = Logger::DEBUG
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'still returns output' do
|
|
39
|
+
resp = conn.get '/hello', nil, accept: 'text/html'
|
|
40
|
+
expect(resp.body).to eq('hello')
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context 'without configuration' do
|
|
44
|
+
let(:conn) do
|
|
45
|
+
Faraday.new do |b|
|
|
46
|
+
b.response :logger
|
|
47
|
+
b.adapter :test do |stubs|
|
|
48
|
+
stubs.get('/hello') { [200, { 'Content-Type' => 'text/html' }, 'hello'] }
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'defaults to stdout' do
|
|
54
|
+
expect(Logger).to receive(:new).with($stdout).and_return(Logger.new(nil))
|
|
55
|
+
conn.get('/hello')
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
context 'when logger with program name' do
|
|
60
|
+
let(:logger) { Logger.new(string_io, progname: 'my_best_program') }
|
|
61
|
+
|
|
62
|
+
it 'logs with program name' do
|
|
63
|
+
conn.get '/hello'
|
|
64
|
+
|
|
65
|
+
expect(string_io.string).to match('-- my_best_program: request:')
|
|
66
|
+
expect(string_io.string).to match('-- my_best_program: response:')
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context 'when logger without program name' do
|
|
71
|
+
it 'logs without program name' do
|
|
72
|
+
conn.get '/hello'
|
|
73
|
+
|
|
74
|
+
expect(string_io.string).to match('-- : request:')
|
|
75
|
+
expect(string_io.string).to match('-- : response:')
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
context 'with default formatter' do
|
|
80
|
+
let(:formatter) { instance_double(Faraday::Logging::Formatter, request: true, response: true, filter: []) }
|
|
81
|
+
|
|
82
|
+
before { allow(Faraday::Logging::Formatter).to receive(:new).and_return(formatter) }
|
|
83
|
+
|
|
84
|
+
it 'delegates logging to the formatter' do
|
|
85
|
+
expect(formatter).to receive(:request).with(an_instance_of(Faraday::Env))
|
|
86
|
+
expect(formatter).to receive(:response).with(an_instance_of(Faraday::Env))
|
|
87
|
+
conn.get '/hello'
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
context 'when no route' do
|
|
91
|
+
it 'delegates logging to the formatter' do
|
|
92
|
+
expect(formatter).to receive(:request).with(an_instance_of(Faraday::Env))
|
|
93
|
+
expect(formatter).to receive(:exception).with(an_instance_of(Faraday::Adapter::Test::Stubs::NotFound))
|
|
94
|
+
|
|
95
|
+
expect { conn.get '/noroute' }.to raise_error(Faraday::Adapter::Test::Stubs::NotFound)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
context 'with custom formatter' do
|
|
101
|
+
let(:formatter_class) do
|
|
102
|
+
Class.new(Faraday::Logging::Formatter) do
|
|
103
|
+
def request(_env)
|
|
104
|
+
info 'Custom log formatter request'
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def response(_env)
|
|
108
|
+
info 'Custom log formatter response'
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
let(:logger_options) { { formatter: formatter_class } }
|
|
114
|
+
|
|
115
|
+
it 'logs with custom formatter' do
|
|
116
|
+
conn.get '/hello'
|
|
117
|
+
|
|
118
|
+
expect(string_io.string).to match('Custom log formatter request')
|
|
119
|
+
expect(string_io.string).to match('Custom log formatter response')
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it 'logs method and url' do
|
|
124
|
+
conn.get '/hello', nil, accept: 'text/html'
|
|
125
|
+
expect(string_io.string).to match('GET http:/hello')
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it 'logs status' do
|
|
129
|
+
conn.get '/hello', nil, accept: 'text/html'
|
|
130
|
+
expect(string_io.string).to match('Status 200')
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it 'does not log error message by default' do
|
|
134
|
+
expect { conn.get '/noroute' }.to raise_error(Faraday::Adapter::Test::Stubs::NotFound)
|
|
135
|
+
expect(string_io.string).not_to match(%(no stubbed request for get http:/noroute))
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it 'logs request headers by default' do
|
|
139
|
+
conn.get '/hello', nil, accept: 'text/html'
|
|
140
|
+
expect(string_io.string).to match(%(Accept: "text/html))
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it 'logs response headers by default' do
|
|
144
|
+
conn.get '/hello', nil, accept: 'text/html'
|
|
145
|
+
expect(string_io.string).to match(%(Content-Type: "text/html))
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it 'does not log request body by default' do
|
|
149
|
+
conn.post '/ohai', 'name=Unagi', accept: 'text/html'
|
|
150
|
+
expect(string_io.string).not_to match(%(name=Unagi))
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
it 'does not log response body by default' do
|
|
154
|
+
conn.post '/ohai', 'name=Toro', accept: 'text/html'
|
|
155
|
+
expect(string_io.string).not_to match(%(fred))
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it 'logs filter headers' do
|
|
159
|
+
conn.headers = { 'api_key' => 'ABC123' }
|
|
160
|
+
conn.get '/filtered_headers', nil, accept: 'text/html'
|
|
161
|
+
expect(string_io.string).to match(%(api_key:))
|
|
162
|
+
expect(string_io.string).to match(%([API_KEY]))
|
|
163
|
+
expect(string_io.string).not_to match(%(ABC123))
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it 'logs filter url' do
|
|
167
|
+
conn.get '/filtered_url?password=hunter2', nil, accept: 'text/html'
|
|
168
|
+
expect(string_io.string).to match(%([HIDDEN]))
|
|
169
|
+
expect(string_io.string).not_to match(%(hunter2))
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
context 'when not logging request headers' do
|
|
173
|
+
let(:logger_options) { { headers: { request: false } } }
|
|
174
|
+
|
|
175
|
+
it 'does not log request headers if option is false' do
|
|
176
|
+
conn.get '/hello', nil, accept: 'text/html'
|
|
177
|
+
expect(string_io.string).not_to match(%(Accept: "text/html))
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
context 'when not logging response headers' do
|
|
182
|
+
let(:logger_options) { { headers: { response: false } } }
|
|
183
|
+
|
|
184
|
+
it 'does not log response headers if option is false' do
|
|
185
|
+
conn.get '/hello', nil, accept: 'text/html'
|
|
186
|
+
expect(string_io.string).not_to match(%(Content-Type: "text/html))
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
context 'when logging request body' do
|
|
191
|
+
let(:logger_options) { { bodies: { request: true } } }
|
|
192
|
+
|
|
193
|
+
it 'logs only request body' do
|
|
194
|
+
conn.post '/ohyes', 'name=Tamago', accept: 'text/html'
|
|
195
|
+
expect(string_io.string).to match(%(name=Tamago))
|
|
196
|
+
expect(string_io.string).not_to match(%(pebbles))
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
context 'when logging response body' do
|
|
201
|
+
let(:logger_options) { { bodies: { response: true } } }
|
|
202
|
+
|
|
203
|
+
it 'logs only response body' do
|
|
204
|
+
conn.post '/ohyes', 'name=Hamachi', accept: 'text/html'
|
|
205
|
+
expect(string_io.string).to match(%(pebbles))
|
|
206
|
+
expect(string_io.string).not_to match(%(name=Hamachi))
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
context 'when logging request and response bodies' do
|
|
211
|
+
let(:logger_options) { { bodies: true } }
|
|
212
|
+
|
|
213
|
+
it 'logs request and response body' do
|
|
214
|
+
conn.post '/ohyes', 'name=Ebi', accept: 'text/html'
|
|
215
|
+
expect(string_io.string).to match(%(name=Ebi))
|
|
216
|
+
expect(string_io.string).to match(%(pebbles))
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
it 'logs response body object' do
|
|
220
|
+
conn.get '/rubbles', nil, accept: 'text/html'
|
|
221
|
+
expect(string_io.string).to match(%(["Barney", "Betty", "Bam Bam"]\n))
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
it 'logs filter body' do
|
|
225
|
+
conn.get '/filtered_body', nil, accept: 'text/html'
|
|
226
|
+
expect(string_io.string).to match(%(soylent green is))
|
|
227
|
+
expect(string_io.string).to match(%(tasty))
|
|
228
|
+
expect(string_io.string).not_to match(%(people))
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
context 'when bodies are logged by default' do
|
|
233
|
+
before do
|
|
234
|
+
described_class.default_options = { bodies: true }
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
it 'logs response body' do
|
|
238
|
+
conn.post '/ohai'
|
|
239
|
+
expect(string_io.string).to match(%(fred))
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
it 'converts to UTF-8' do
|
|
243
|
+
conn.get '/8bit'
|
|
244
|
+
expect(string_io.string).to match(%(caf��!))
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
after do
|
|
248
|
+
described_class.default_options = { bodies: false }
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
context 'when logging errors' do
|
|
253
|
+
let(:logger_options) { { errors: true } }
|
|
254
|
+
|
|
255
|
+
it 'logs error message' do
|
|
256
|
+
expect { conn.get '/noroute' }.to raise_error(Faraday::Adapter::Test::Stubs::NotFound)
|
|
257
|
+
expect(string_io.string).to match(%(no stubbed request for get http:/noroute))
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
context 'when logging headers and errors' do
|
|
262
|
+
let(:logger_options) { { headers: true, errors: true } }
|
|
263
|
+
|
|
264
|
+
it 'logs error message' do
|
|
265
|
+
expect { conn.get '/connection_failed' }.to raise_error(Faraday::ConnectionFailed)
|
|
266
|
+
expect(string_io.string).to match(%(Failed to open TCP connection))
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
context 'when using log_level' do
|
|
271
|
+
let(:logger_options) { { bodies: true, log_level: :debug } }
|
|
272
|
+
|
|
273
|
+
it 'logs request/request body on the specified level (debug)' do
|
|
274
|
+
logger.level = Logger::DEBUG
|
|
275
|
+
conn.post '/ohyes', 'name=Ebi', accept: 'text/html'
|
|
276
|
+
expect(string_io.string).to match(%(name=Ebi))
|
|
277
|
+
expect(string_io.string).to match(%(pebbles))
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
it 'logs headers on the debug level' do
|
|
281
|
+
logger.level = Logger::DEBUG
|
|
282
|
+
conn.get '/hello', nil, accept: 'text/html'
|
|
283
|
+
expect(string_io.string).to match(%(Content-Type: "text/html))
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
it 'does not log request/response body on the info level' do
|
|
287
|
+
logger.level = Logger::INFO
|
|
288
|
+
conn.post '/ohyes', 'name=Ebi', accept: 'text/html'
|
|
289
|
+
expect(string_io.string).not_to match(%(name=Ebi))
|
|
290
|
+
expect(string_io.string).not_to match(%(pebbles))
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
it 'does not log headers on the info level' do
|
|
294
|
+
logger.level = Logger::INFO
|
|
295
|
+
conn.get '/hello', nil, accept: 'text/html'
|
|
296
|
+
expect(string_io.string).not_to match(%(Content-Type: "text/html))
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
end
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe Faraday::Response::RaiseError do
|
|
4
|
+
let(:conn) do
|
|
5
|
+
Faraday.new do |b|
|
|
6
|
+
b.response :raise_error
|
|
7
|
+
b.adapter :test do |stub|
|
|
8
|
+
stub.get('ok') { [200, { 'Content-Type' => 'text/html' }, '<body></body>'] }
|
|
9
|
+
stub.get('bad-request') { [400, { 'X-Reason' => 'because' }, 'keep looking'] }
|
|
10
|
+
stub.get('unauthorized') { [401, { 'X-Reason' => 'because' }, 'keep looking'] }
|
|
11
|
+
stub.get('forbidden') { [403, { 'X-Reason' => 'because' }, 'keep looking'] }
|
|
12
|
+
stub.get('not-found') { [404, { 'X-Reason' => 'because' }, 'keep looking'] }
|
|
13
|
+
stub.get('proxy-error') { [407, { 'X-Reason' => 'because' }, 'keep looking'] }
|
|
14
|
+
stub.get('request-timeout') { [408, { 'X-Reason' => 'because' }, 'keep looking'] }
|
|
15
|
+
stub.get('conflict') { [409, { 'X-Reason' => 'because' }, 'keep looking'] }
|
|
16
|
+
stub.get('unprocessable-content') { [422, { 'X-Reason' => 'because' }, 'keep looking'] }
|
|
17
|
+
stub.get('too-many-requests') { [429, { 'X-Reason' => 'because' }, 'keep looking'] }
|
|
18
|
+
stub.get('4xx') { [499, { 'X-Reason' => 'because' }, 'keep looking'] }
|
|
19
|
+
stub.get('nil-status') { [nil, { 'X-Reason' => 'nil' }, 'fail'] }
|
|
20
|
+
stub.get('server-error') { [500, { 'X-Error' => 'bailout' }, 'fail'] }
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'raises no exception for 200 responses' do
|
|
26
|
+
expect { conn.get('ok') }.not_to raise_error
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'raises Faraday::BadRequestError for 400 responses' do
|
|
30
|
+
expect { conn.get('bad-request') }.to raise_error(Faraday::BadRequestError) do |ex|
|
|
31
|
+
expect(ex.message).to eq('the server responded with status 400 for GET http:/bad-request')
|
|
32
|
+
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
|
33
|
+
expect(ex.response[:status]).to eq(400)
|
|
34
|
+
expect(ex.response_status).to eq(400)
|
|
35
|
+
expect(ex.response_body).to eq('keep looking')
|
|
36
|
+
expect(ex.response_headers['X-Reason']).to eq('because')
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'raises Faraday::UnauthorizedError for 401 responses' do
|
|
41
|
+
expect { conn.get('unauthorized') }.to raise_error(Faraday::UnauthorizedError) do |ex|
|
|
42
|
+
expect(ex.message).to eq('the server responded with status 401 for GET http:/unauthorized')
|
|
43
|
+
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
|
44
|
+
expect(ex.response[:status]).to eq(401)
|
|
45
|
+
expect(ex.response_status).to eq(401)
|
|
46
|
+
expect(ex.response_body).to eq('keep looking')
|
|
47
|
+
expect(ex.response_headers['X-Reason']).to eq('because')
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'raises Faraday::ForbiddenError for 403 responses' do
|
|
52
|
+
expect { conn.get('forbidden') }.to raise_error(Faraday::ForbiddenError) do |ex|
|
|
53
|
+
expect(ex.message).to eq('the server responded with status 403 for GET http:/forbidden')
|
|
54
|
+
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
|
55
|
+
expect(ex.response[:status]).to eq(403)
|
|
56
|
+
expect(ex.response_status).to eq(403)
|
|
57
|
+
expect(ex.response_body).to eq('keep looking')
|
|
58
|
+
expect(ex.response_headers['X-Reason']).to eq('because')
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it 'raises Faraday::ResourceNotFound for 404 responses' do
|
|
63
|
+
expect { conn.get('not-found') }.to raise_error(Faraday::ResourceNotFound) do |ex|
|
|
64
|
+
expect(ex.message).to eq('the server responded with status 404 for GET http:/not-found')
|
|
65
|
+
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
|
66
|
+
expect(ex.response[:status]).to eq(404)
|
|
67
|
+
expect(ex.response_status).to eq(404)
|
|
68
|
+
expect(ex.response_body).to eq('keep looking')
|
|
69
|
+
expect(ex.response_headers['X-Reason']).to eq('because')
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'raises Faraday::ProxyAuthError for 407 responses' do
|
|
74
|
+
expect { conn.get('proxy-error') }.to raise_error(Faraday::ProxyAuthError) do |ex|
|
|
75
|
+
expect(ex.message).to eq('407 "Proxy Authentication Required"')
|
|
76
|
+
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
|
77
|
+
expect(ex.response[:status]).to eq(407)
|
|
78
|
+
expect(ex.response_status).to eq(407)
|
|
79
|
+
expect(ex.response_body).to eq('keep looking')
|
|
80
|
+
expect(ex.response_headers['X-Reason']).to eq('because')
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it 'raises Faraday::RequestTimeoutError for 408 responses' do
|
|
85
|
+
expect { conn.get('request-timeout') }.to raise_error(Faraday::RequestTimeoutError) do |ex|
|
|
86
|
+
expect(ex.message).to eq('the server responded with status 408 for GET http:/request-timeout')
|
|
87
|
+
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
|
88
|
+
expect(ex.response[:status]).to eq(408)
|
|
89
|
+
expect(ex.response_status).to eq(408)
|
|
90
|
+
expect(ex.response_body).to eq('keep looking')
|
|
91
|
+
expect(ex.response_headers['X-Reason']).to eq('because')
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'raises Faraday::ConflictError for 409 responses' do
|
|
96
|
+
expect { conn.get('conflict') }.to raise_error(Faraday::ConflictError) do |ex|
|
|
97
|
+
expect(ex.message).to eq('the server responded with status 409 for GET http:/conflict')
|
|
98
|
+
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
|
99
|
+
expect(ex.response[:status]).to eq(409)
|
|
100
|
+
expect(ex.response_status).to eq(409)
|
|
101
|
+
expect(ex.response_body).to eq('keep looking')
|
|
102
|
+
expect(ex.response_headers['X-Reason']).to eq('because')
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it 'raises legacy Faraday::UnprocessableEntityError for 422 responses' do
|
|
107
|
+
expect { conn.get('unprocessable-content') }.to raise_error(Faraday::UnprocessableEntityError) do |ex|
|
|
108
|
+
expect(ex.message).to eq('the server responded with status 422 for GET http:/unprocessable-content')
|
|
109
|
+
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
|
110
|
+
expect(ex.response[:status]).to eq(422)
|
|
111
|
+
expect(ex.response_status).to eq(422)
|
|
112
|
+
expect(ex.response_body).to eq('keep looking')
|
|
113
|
+
expect(ex.response_headers['X-Reason']).to eq('because')
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it 'raises Faraday::UnprocessableContentError for 422 responses' do
|
|
118
|
+
expect { conn.get('unprocessable-content') }.to raise_error(Faraday::UnprocessableContentError) do |ex|
|
|
119
|
+
expect(ex.message).to eq('the server responded with status 422 for GET http:/unprocessable-content')
|
|
120
|
+
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
|
121
|
+
expect(ex.response[:status]).to eq(422)
|
|
122
|
+
expect(ex.response_status).to eq(422)
|
|
123
|
+
expect(ex.response_body).to eq('keep looking')
|
|
124
|
+
expect(ex.response_headers['X-Reason']).to eq('because')
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it 'raises Faraday::TooManyRequestsError for 429 responses' do
|
|
129
|
+
expect { conn.get('too-many-requests') }.to raise_error(Faraday::TooManyRequestsError) do |ex|
|
|
130
|
+
expect(ex.message).to eq('the server responded with status 429 for GET http:/too-many-requests')
|
|
131
|
+
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
|
132
|
+
expect(ex.response[:status]).to eq(429)
|
|
133
|
+
expect(ex.response_status).to eq(429)
|
|
134
|
+
expect(ex.response_body).to eq('keep looking')
|
|
135
|
+
expect(ex.response_headers['X-Reason']).to eq('because')
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it 'raises Faraday::NilStatusError for nil status in response' do
|
|
140
|
+
expect { conn.get('nil-status') }.to raise_error(Faraday::NilStatusError) do |ex|
|
|
141
|
+
expect(ex.message).to eq('http status could not be derived from the server response')
|
|
142
|
+
expect(ex.response[:headers]['X-Reason']).to eq('nil')
|
|
143
|
+
expect(ex.response[:status]).to be_nil
|
|
144
|
+
expect(ex.response_status).to be_nil
|
|
145
|
+
expect(ex.response_body).to eq('fail')
|
|
146
|
+
expect(ex.response_headers['X-Reason']).to eq('nil')
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it 'raises Faraday::ClientError for other 4xx responses' do
|
|
151
|
+
expect { conn.get('4xx') }.to raise_error(Faraday::ClientError) do |ex|
|
|
152
|
+
expect(ex.message).to eq('the server responded with status 499 for GET http:/4xx')
|
|
153
|
+
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
|
154
|
+
expect(ex.response[:status]).to eq(499)
|
|
155
|
+
expect(ex.response_status).to eq(499)
|
|
156
|
+
expect(ex.response_body).to eq('keep looking')
|
|
157
|
+
expect(ex.response_headers['X-Reason']).to eq('because')
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it 'raises Faraday::ServerError for 500 responses' do
|
|
162
|
+
expect { conn.get('server-error') }.to raise_error(Faraday::ServerError) do |ex|
|
|
163
|
+
expect(ex.message).to eq('the server responded with status 500 for GET http:/server-error')
|
|
164
|
+
expect(ex.response[:headers]['X-Error']).to eq('bailout')
|
|
165
|
+
expect(ex.response[:status]).to eq(500)
|
|
166
|
+
expect(ex.response_status).to eq(500)
|
|
167
|
+
expect(ex.response_body).to eq('fail')
|
|
168
|
+
expect(ex.response_headers['X-Error']).to eq('bailout')
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
describe 'request info' do
|
|
173
|
+
let(:conn) do
|
|
174
|
+
Faraday.new do |b|
|
|
175
|
+
b.response :raise_error, **middleware_options
|
|
176
|
+
b.adapter :test do |stub|
|
|
177
|
+
stub.post(url, request_body, request_headers) do
|
|
178
|
+
[400, { 'X-Reason' => 'because' }, 'keep looking']
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
let(:middleware_options) { {} }
|
|
184
|
+
let(:request_body) { JSON.generate({ 'item' => 'sth' }) }
|
|
185
|
+
let(:request_headers) { { 'Authorization' => 'Basic 123' } }
|
|
186
|
+
let(:url_path) { 'request' }
|
|
187
|
+
let(:query_params) { 'full=true' }
|
|
188
|
+
let(:url) { "#{url_path}?#{query_params}" }
|
|
189
|
+
|
|
190
|
+
subject(:perform_request) do
|
|
191
|
+
conn.post url do |req|
|
|
192
|
+
req.headers['Authorization'] = 'Basic 123'
|
|
193
|
+
req.body = request_body
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
it 'returns the request info in the exception' do
|
|
198
|
+
expect { perform_request }.to raise_error(Faraday::BadRequestError) do |ex|
|
|
199
|
+
expect(ex.response[:request][:method]).to eq(:post)
|
|
200
|
+
expect(ex.response[:request][:url]).to eq(URI("http:/#{url}"))
|
|
201
|
+
expect(ex.response[:request][:url_path]).to eq("/#{url_path}")
|
|
202
|
+
expect(ex.response[:request][:params]).to eq({ 'full' => 'true' })
|
|
203
|
+
expect(ex.response[:request][:headers]).to match(a_hash_including(request_headers))
|
|
204
|
+
expect(ex.response[:request][:body]).to eq(request_body)
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
describe 'DEFAULT_OPTION: include_request' do
|
|
209
|
+
before(:each) do
|
|
210
|
+
Faraday::Response::RaiseError.instance_variable_set(:@default_options, nil)
|
|
211
|
+
Faraday::Middleware.instance_variable_set(:@default_options, nil)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
after(:all) do
|
|
215
|
+
Faraday::Response::RaiseError.instance_variable_set(:@default_options, nil)
|
|
216
|
+
Faraday::Middleware.instance_variable_set(:@default_options, nil)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
context 'when RaiseError DEFAULT_OPTION (include_request: true) is used' do
|
|
220
|
+
it 'includes request info in the exception' do
|
|
221
|
+
expect { perform_request }.to raise_error(Faraday::BadRequestError) do |ex|
|
|
222
|
+
expect(ex.response.keys).to contain_exactly(
|
|
223
|
+
:status,
|
|
224
|
+
:headers,
|
|
225
|
+
:body,
|
|
226
|
+
:request
|
|
227
|
+
)
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
context 'when application sets default_options `include_request: false`' do
|
|
233
|
+
before(:each) do
|
|
234
|
+
Faraday::Response::RaiseError.default_options = { include_request: false }
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
context 'and when include_request option is omitted' do
|
|
238
|
+
it 'does not include request info in the exception' do
|
|
239
|
+
expect { perform_request }.to raise_error(Faraday::BadRequestError) do |ex|
|
|
240
|
+
expect(ex.response.keys).to contain_exactly(
|
|
241
|
+
:status,
|
|
242
|
+
:headers,
|
|
243
|
+
:body
|
|
244
|
+
)
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
context 'and when include_request option is explicitly set for instance' do
|
|
250
|
+
let(:middleware_options) { { include_request: true } }
|
|
251
|
+
|
|
252
|
+
it 'includes request info in the exception' do
|
|
253
|
+
expect { perform_request }.to raise_error(Faraday::BadRequestError) do |ex|
|
|
254
|
+
expect(ex.response.keys).to contain_exactly(
|
|
255
|
+
:status,
|
|
256
|
+
:headers,
|
|
257
|
+
:body,
|
|
258
|
+
:request
|
|
259
|
+
)
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
describe 'allowing certain status codes' do
|
|
268
|
+
let(:conn) do
|
|
269
|
+
Faraday.new do |b|
|
|
270
|
+
b.response :raise_error, allowed_statuses: [404]
|
|
271
|
+
b.adapter :test do |stub|
|
|
272
|
+
stub.get('bad-request') { [400, { 'X-Reason' => 'because' }, 'keep looking'] }
|
|
273
|
+
stub.get('not-found') { [404, { 'X-Reason' => 'because' }, 'keep looking'] }
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
it 'raises an error for status codes that are not explicitly allowed' do
|
|
279
|
+
expect { conn.get('bad-request') }.to raise_error(Faraday::BadRequestError)
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
it 'does not raise an error for allowed status codes' do
|
|
283
|
+
expect { conn.get('not-found') }.not_to raise_error
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe Faraday::Response do
|
|
4
|
+
subject { Faraday::Response.new(env) }
|
|
5
|
+
|
|
6
|
+
let(:env) do
|
|
7
|
+
Faraday::Env.from(status: 404, body: 'yikes', url: Faraday::Utils.URI('https://lostisland.github.io/faraday'),
|
|
8
|
+
response_headers: { 'Content-Type' => 'text/plain' })
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it { expect(subject.finished?).to be_truthy }
|
|
12
|
+
it { expect { subject.finish({}) }.to raise_error(RuntimeError) }
|
|
13
|
+
it { expect(subject.success?).to be_falsey }
|
|
14
|
+
it { expect(subject.status).to eq(404) }
|
|
15
|
+
it { expect(subject.body).to eq('yikes') }
|
|
16
|
+
it { expect(subject.url).to eq(URI('https://lostisland.github.io/faraday')) }
|
|
17
|
+
it { expect(subject.headers['Content-Type']).to eq('text/plain') }
|
|
18
|
+
it { expect(subject['content-type']).to eq('text/plain') }
|
|
19
|
+
|
|
20
|
+
describe '#apply_request' do
|
|
21
|
+
before { subject.apply_request(body: 'a=b', method: :post) }
|
|
22
|
+
|
|
23
|
+
it { expect(subject.body).to eq('yikes') }
|
|
24
|
+
it { expect(subject.env[:method]).to eq(:post) }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe '#to_hash' do
|
|
28
|
+
let(:hash) { subject.to_hash }
|
|
29
|
+
|
|
30
|
+
it { expect(hash).to be_a(Hash) }
|
|
31
|
+
it { expect(hash[:status]).to eq(subject.status) }
|
|
32
|
+
it { expect(hash[:response_headers]).to eq(subject.headers) }
|
|
33
|
+
it { expect(hash[:body]).to eq(subject.body) }
|
|
34
|
+
it { expect(hash[:url]).to eq(subject.env.url) }
|
|
35
|
+
|
|
36
|
+
context 'when response is not finished' do
|
|
37
|
+
subject { Faraday::Response.new.to_hash }
|
|
38
|
+
|
|
39
|
+
it { is_expected.to eq({ status: nil, body: nil, response_headers: {}, url: nil }) }
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe 'marshal serialization support' do
|
|
44
|
+
subject { Faraday::Response.new }
|
|
45
|
+
let(:loaded) { Marshal.load(Marshal.dump(subject)) }
|
|
46
|
+
|
|
47
|
+
before do
|
|
48
|
+
subject.on_complete {}
|
|
49
|
+
subject.finish(env.merge(params: 'moo'))
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it { expect(loaded.env[:params]).to be_nil }
|
|
53
|
+
it { expect(loaded.env[:body]).to eq(env[:body]) }
|
|
54
|
+
it { expect(loaded.env[:response_headers]).to eq(env[:response_headers]) }
|
|
55
|
+
it { expect(loaded.env[:status]).to eq(env[:status]) }
|
|
56
|
+
it { expect(loaded.env[:url]).to eq(env[:url]) }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
describe '#on_complete' do
|
|
60
|
+
subject { Faraday::Response.new }
|
|
61
|
+
|
|
62
|
+
it 'parse body on finish' do
|
|
63
|
+
subject.on_complete { |env| env[:body] = env[:body].upcase }
|
|
64
|
+
subject.finish(env)
|
|
65
|
+
|
|
66
|
+
expect(subject.body).to eq('YIKES')
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'can access response body in on_complete callback' do
|
|
70
|
+
subject.on_complete { |env| env[:body] = subject.body.upcase }
|
|
71
|
+
subject.finish(env)
|
|
72
|
+
|
|
73
|
+
expect(subject.body).to eq('YIKES')
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it 'can access response body in on_complete callback' do
|
|
77
|
+
callback_env = nil
|
|
78
|
+
subject.on_complete { |env| callback_env = env }
|
|
79
|
+
subject.finish({})
|
|
80
|
+
|
|
81
|
+
expect(subject.env).to eq(callback_env)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|