committee 3.0.3 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/committee/middleware/base.rb +1 -0
- data/lib/committee/middleware/request_validation.rb +2 -0
- data/lib/committee/middleware/response_validation.rb +0 -2
- data/lib/committee/schema_validator/open_api_3/operation_wrapper.rb +1 -1
- data/lib/committee/test/methods.rb +40 -5
- data/test/middleware/request_validation_open_api_3_test.rb +11 -0
- data/test/middleware/request_validation_test.rb +33 -0
- data/test/schema_validator/hyper_schema/response_generator_test.rb +1 -1
- data/test/schema_validator/hyper_schema/response_validator_test.rb +2 -2
- data/test/test/methods_test.rb +133 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0261ef5b9991afdc79316a4aa67e05293b5cc0dc83a8b7dc80a330fcc2d633b9
|
4
|
+
data.tar.gz: a67badbaa49fa492e9bd562293666734a9c733a9d5fa8c54b6a7cf6b3a414305
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8de3637d5059cb2dee41b9d78aa6b448d3c60fc246485bca06cbceb1e2f993c8b86f9d76a9388359c1f05b05e429eaf5949d6e6dfd587246ac4ab8c59f0f37bd
|
7
|
+
data.tar.gz: 510f84e62e9f52239845130b14a6f9432bc2c391c92ab5334b74b301c9119378a491add7f7cfb33fd711a522b727da325a045be31e04ac94fd8c0ead858042a6
|
@@ -17,6 +17,7 @@ module Committee::Middleware
|
|
17
17
|
|
18
18
|
@app.call(request.env)
|
19
19
|
rescue Committee::BadRequest, Committee::InvalidRequest
|
20
|
+
@error_handler.call($!) if @error_handler
|
20
21
|
raise if @raise
|
21
22
|
@error_class.new(400, :bad_request, $!.message).render
|
22
23
|
rescue Committee::NotFound => e
|
@@ -27,6 +28,7 @@ module Committee::Middleware
|
|
27
28
|
e.message
|
28
29
|
).render
|
29
30
|
rescue JSON::ParserError
|
31
|
+
@error_handler.call($!) if @error_handler
|
30
32
|
raise Committee::InvalidRequest if @raise
|
31
33
|
@error_class.new(400, :bad_request, "Request body wasn't valid JSON.").render
|
32
34
|
end
|
@@ -18,7 +18,7 @@ module Committee
|
|
18
18
|
return {} unless options.coerce_value
|
19
19
|
|
20
20
|
request_operation.validate_path_params(options)
|
21
|
-
rescue OpenAPIParser::
|
21
|
+
rescue OpenAPIParser::OpenAPIError => e
|
22
22
|
raise Committee::InvalidRequest.new(e.message)
|
23
23
|
end
|
24
24
|
|
@@ -1,18 +1,27 @@
|
|
1
1
|
module Committee::Test
|
2
2
|
module Methods
|
3
3
|
def assert_schema_conform
|
4
|
-
|
5
|
-
|
4
|
+
assert_request_schema_confirm unless old_behavior
|
5
|
+
assert_response_schema_confirm
|
6
|
+
end
|
7
|
+
|
8
|
+
def assert_request_schema_confirm
|
9
|
+
unless schema_validator.link_exist?
|
10
|
+
request = "`#{request_object.request_method} #{request_object.path_info}` undefined in schema."
|
11
|
+
raise Committee::InvalidRequest.new(request)
|
12
|
+
end
|
6
13
|
|
7
|
-
|
14
|
+
schema_validator.request_validate(request_object)
|
15
|
+
end
|
8
16
|
|
9
|
-
|
17
|
+
def assert_response_schema_confirm
|
18
|
+
unless schema_validator.link_exist?
|
10
19
|
response = "`#{request_object.request_method} #{request_object.path_info}` undefined in schema."
|
11
20
|
raise Committee::InvalidResponse.new(response)
|
12
21
|
end
|
13
22
|
|
14
23
|
status, headers, body = response_data
|
15
|
-
|
24
|
+
schema_validator.response_validate(status, headers, [body], true) if validate_response?(status)
|
16
25
|
end
|
17
26
|
|
18
27
|
def committee_options
|
@@ -30,5 +39,31 @@ module Committee::Test
|
|
30
39
|
def validate_response?(status)
|
31
40
|
Committee::Middleware::ResponseValidation.validate?(status, committee_options.fetch(:validate_success_only, false))
|
32
41
|
end
|
42
|
+
|
43
|
+
def schema
|
44
|
+
@schema ||= Committee::Middleware::Base.get_schema(committee_options)
|
45
|
+
end
|
46
|
+
|
47
|
+
def router
|
48
|
+
@router ||= schema.build_router(committee_options)
|
49
|
+
end
|
50
|
+
|
51
|
+
def schema_validator
|
52
|
+
@schema_validator ||= router.build_schema_validator(request_object)
|
53
|
+
end
|
54
|
+
|
55
|
+
def old_behavior
|
56
|
+
old_assert_behavior = committee_options.fetch(:old_assert_behavior, nil)
|
57
|
+
if old_assert_behavior.nil?
|
58
|
+
warn <<-MSG
|
59
|
+
[DEPRECATION] now assert_schema_confirm check response schema only.
|
60
|
+
but we will change check request and response in future major version.
|
61
|
+
so if you want to conform response only, please use assert_response_schema_confirm,
|
62
|
+
or you can suppress this message and keep old behavior by setting old_assert_behavior=true.
|
63
|
+
MSG
|
64
|
+
old_assert_behavior = true
|
65
|
+
end
|
66
|
+
old_assert_behavior
|
67
|
+
end
|
33
68
|
end
|
34
69
|
end
|
@@ -322,6 +322,17 @@ describe Committee::Middleware::RequestValidation do
|
|
322
322
|
assert_match(/required parameters query_string not exist in/i, e.message)
|
323
323
|
end
|
324
324
|
|
325
|
+
it "raises error when required path parameter is invalid" do
|
326
|
+
@app = new_rack_app(raise: true, schema: open_api_3_schema)
|
327
|
+
|
328
|
+
e = assert_raises(Committee::InvalidRequest) do
|
329
|
+
not_an_integer = 'abc'
|
330
|
+
get "/coerce_path_params/#{not_an_integer}", nil
|
331
|
+
end
|
332
|
+
|
333
|
+
assert_match(/is String but it's not valid integer in/i, e.message)
|
334
|
+
end
|
335
|
+
|
325
336
|
it "optionally raises an error" do
|
326
337
|
@app = new_rack_app(raise: true, schema: open_api_3_schema)
|
327
338
|
header "Content-Type", "application/json"
|
@@ -61,6 +61,18 @@ describe Committee::Middleware::RequestValidation do
|
|
61
61
|
assert_equal 200, last_response.status
|
62
62
|
end
|
63
63
|
|
64
|
+
it "doesn't call error_handler when request is valid" do
|
65
|
+
called_error = false
|
66
|
+
pr = ->(_) { called_error = true }
|
67
|
+
@app = new_rack_app(schema: hyper_schema, error_handler: pr)
|
68
|
+
params = {
|
69
|
+
"name" => "cloudnasium"
|
70
|
+
}
|
71
|
+
header "Content-Type", "application/json"
|
72
|
+
post "/apps", JSON.generate(params)
|
73
|
+
assert !called_error
|
74
|
+
end
|
75
|
+
|
64
76
|
it "passes given a datetime and with coerce_date_times enabled on GET endpoint" do
|
65
77
|
key_name = "update_time"
|
66
78
|
params = {
|
@@ -270,6 +282,18 @@ describe Committee::Middleware::RequestValidation do
|
|
270
282
|
assert_match(/invalid request/i, last_response.body)
|
271
283
|
end
|
272
284
|
|
285
|
+
it "calls error_handler when request is invalid" do
|
286
|
+
called_err = nil
|
287
|
+
pr = ->(e) { called_err = e }
|
288
|
+
@app = new_rack_app(schema: hyper_schema, error_handler: pr)
|
289
|
+
header "Content-Type", "application/json"
|
290
|
+
params = {
|
291
|
+
"name" => 1
|
292
|
+
}
|
293
|
+
post "/apps", JSON.generate(params)
|
294
|
+
assert_kind_of Committee::InvalidRequest, called_err
|
295
|
+
end
|
296
|
+
|
273
297
|
it "rescues JSON errors" do
|
274
298
|
@app = new_rack_app(schema: hyper_schema)
|
275
299
|
header "Content-Type", "application/json"
|
@@ -278,6 +302,15 @@ describe Committee::Middleware::RequestValidation do
|
|
278
302
|
assert_match(/valid json/i, last_response.body)
|
279
303
|
end
|
280
304
|
|
305
|
+
it "calls error_handler when it rescues JSON errors" do
|
306
|
+
called_err = nil
|
307
|
+
pr = ->(e) { called_err = e }
|
308
|
+
@app = new_rack_app(schema: hyper_schema, error_handler: pr)
|
309
|
+
header "Content-Type", "application/json"
|
310
|
+
post "/apps", "{x:y}"
|
311
|
+
assert_kind_of JSON::ParserError, called_err
|
312
|
+
end
|
313
|
+
|
281
314
|
it "takes a prefix" do
|
282
315
|
@app = new_rack_app(prefix: "/v1", schema: hyper_schema)
|
283
316
|
params = {
|
@@ -43,7 +43,7 @@ describe Committee::SchemaValidator::HyperSchema::ResponseGenerator do
|
|
43
43
|
data, _schema = call
|
44
44
|
|
45
45
|
# We're testing for legacy behavior here: even without a `targetSchema` as
|
46
|
-
# long as `rel` is set to `instances` we still wrap the
|
46
|
+
# long as `rel` is set to `instances` we still wrap the result in an
|
47
47
|
# array.
|
48
48
|
assert_equal "instances", @list_link.rel
|
49
49
|
|
@@ -43,7 +43,7 @@ describe Committee::SchemaValidator::HyperSchema::ResponseValidator do
|
|
43
43
|
@link.target_schema = nil
|
44
44
|
|
45
45
|
# We're testing for legacy behavior here: even without a `targetSchema` as
|
46
|
-
# long as `rel` is set to `instances` we still wrap the
|
46
|
+
# long as `rel` is set to `instances` we still wrap the result in an
|
47
47
|
# array.
|
48
48
|
assert_equal "instances", @link.rel
|
49
49
|
|
@@ -59,7 +59,7 @@ describe Committee::SchemaValidator::HyperSchema::ResponseValidator do
|
|
59
59
|
@link.target_schema = nil
|
60
60
|
|
61
61
|
# We're testing for legacy behavior here: even without a `targetSchema` as
|
62
|
-
# long as `rel` is set to `instances` we still wrap the
|
62
|
+
# long as `rel` is set to `instances` we still wrap the result in an
|
63
63
|
# array.
|
64
64
|
assert_equal "instances", @link.rel
|
65
65
|
|
data/test/test/methods_test.rb
CHANGED
@@ -52,6 +52,67 @@ describe Committee::Test::Methods do
|
|
52
52
|
end
|
53
53
|
assert_match(/response header must be set to/i, e.message)
|
54
54
|
end
|
55
|
+
|
56
|
+
it "outputs deprecation warning" do
|
57
|
+
@app = new_rack_app(JSON.generate([ValidApp]))
|
58
|
+
get "/apps"
|
59
|
+
_, err = capture_io do
|
60
|
+
assert_schema_conform
|
61
|
+
end
|
62
|
+
assert_match(/\[DEPRECATION\]/i, err)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "assert_request_schema_confirm" do
|
67
|
+
it "passes through a valid request" do
|
68
|
+
@app = new_rack_app([])
|
69
|
+
get "/apps"
|
70
|
+
assert_request_schema_confirm
|
71
|
+
end
|
72
|
+
|
73
|
+
it "not exist required" do
|
74
|
+
@app = new_rack_app([])
|
75
|
+
get "/search/apps", {}
|
76
|
+
e = assert_raises(Committee::InvalidRequest) do
|
77
|
+
assert_request_schema_confirm
|
78
|
+
end
|
79
|
+
assert_match(/"query" wasn't supplied\./i, e.message)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "path undefined in schema" do
|
83
|
+
@app = new_rack_app([])
|
84
|
+
get "/undefined"
|
85
|
+
e = assert_raises(Committee::InvalidRequest) do
|
86
|
+
assert_request_schema_confirm
|
87
|
+
end
|
88
|
+
assert_match(/`GET \/undefined` undefined in schema/i, e.message)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "#assert_response_schema_confirm" do
|
93
|
+
it "passes through a valid response" do
|
94
|
+
@app = new_rack_app(JSON.generate([ValidApp]))
|
95
|
+
get "/apps"
|
96
|
+
assert_response_schema_confirm
|
97
|
+
end
|
98
|
+
|
99
|
+
it "detects an invalid response Content-Type" do
|
100
|
+
@app = new_rack_app(JSON.generate([ValidApp]), {})
|
101
|
+
get "/apps"
|
102
|
+
e = assert_raises(Committee::InvalidResponse) do
|
103
|
+
assert_response_schema_confirm
|
104
|
+
end
|
105
|
+
assert_match(/response header must be set to/i, e.message)
|
106
|
+
end
|
107
|
+
|
108
|
+
it "path undefined in schema" do
|
109
|
+
@app = new_rack_app(JSON.generate([ValidApp]))
|
110
|
+
get "/undefined"
|
111
|
+
e = assert_raises(Committee::InvalidResponse) do
|
112
|
+
assert_response_schema_confirm
|
113
|
+
end
|
114
|
+
assert_match(/`GET \/undefined` undefined in schema/i, e.message)
|
115
|
+
end
|
55
116
|
end
|
56
117
|
end
|
57
118
|
|
@@ -88,6 +149,78 @@ describe Committee::Test::Methods do
|
|
88
149
|
end
|
89
150
|
assert_match(/don't exist status code definition/i, e.message)
|
90
151
|
end
|
152
|
+
|
153
|
+
it "outputs deprecation warning" do
|
154
|
+
@app = new_rack_app(JSON.generate(@correct_response))
|
155
|
+
get "/characters"
|
156
|
+
_, err = capture_io do
|
157
|
+
assert_schema_conform
|
158
|
+
end
|
159
|
+
assert_match(/\[DEPRECATION\]/i, err)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe "assert_request_schema_confirm" do
|
164
|
+
it "passes through a valid request" do
|
165
|
+
@app = new_rack_app([])
|
166
|
+
get "/characters"
|
167
|
+
assert_request_schema_confirm
|
168
|
+
end
|
169
|
+
|
170
|
+
it "not exist required" do
|
171
|
+
@app = new_rack_app([])
|
172
|
+
get "/validate", {"query_string" => "query", "query_integer_list" => [1, 2]}
|
173
|
+
e = assert_raises(Committee::InvalidRequest) do
|
174
|
+
assert_request_schema_confirm
|
175
|
+
end
|
176
|
+
assert_match(/required parameters query_string not exist in #\/paths/i, e.message)
|
177
|
+
end
|
178
|
+
|
179
|
+
it "path undefined in schema" do
|
180
|
+
@app = new_rack_app([])
|
181
|
+
get "/undefined"
|
182
|
+
e = assert_raises(Committee::InvalidRequest) do
|
183
|
+
assert_request_schema_confirm
|
184
|
+
end
|
185
|
+
assert_match(/`GET \/undefined` undefined in schema/i, e.message)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe "#assert_response_schema_confirm" do
|
190
|
+
it "passes through a valid response" do
|
191
|
+
@app = new_rack_app(JSON.generate(@correct_response))
|
192
|
+
get "/characters"
|
193
|
+
assert_response_schema_confirm
|
194
|
+
end
|
195
|
+
|
196
|
+
it "detects an invalid response Content-Type" do
|
197
|
+
@app = new_rack_app(JSON.generate([@correct_response]), {})
|
198
|
+
get "/characters"
|
199
|
+
e = assert_raises(Committee::InvalidResponse) do
|
200
|
+
assert_response_schema_confirm
|
201
|
+
end
|
202
|
+
assert_match(/don't exist response definition/i, e.message)
|
203
|
+
end
|
204
|
+
|
205
|
+
it "detects an invalid response status code" do
|
206
|
+
@app = new_rack_app(JSON.generate([@correct_response]), {}, 419)
|
207
|
+
|
208
|
+
get "/characters"
|
209
|
+
|
210
|
+
e = assert_raises(Committee::InvalidResponse) do
|
211
|
+
assert_response_schema_confirm
|
212
|
+
end
|
213
|
+
assert_match(/don't exist status code definition/i, e.message)
|
214
|
+
end
|
215
|
+
|
216
|
+
it "path undefined in schema" do
|
217
|
+
@app = new_rack_app(JSON.generate(@correct_response))
|
218
|
+
get "/undefined"
|
219
|
+
e = assert_raises(Committee::InvalidResponse) do
|
220
|
+
assert_response_schema_confirm
|
221
|
+
end
|
222
|
+
assert_match(/`GET \/undefined` undefined in schema/i, e.message)
|
223
|
+
end
|
91
224
|
end
|
92
225
|
end
|
93
226
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: committee
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brandur
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2019-
|
13
|
+
date: 2019-08-07 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: json_schema
|