committee 5.6.1 → 5.6.3
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/lib/committee/drivers/open_api_3/driver.rb +7 -1
- data/lib/committee/drivers.rb +2 -3
- data/lib/committee/errors.rb +11 -0
- data/lib/committee/middleware/base.rb +11 -5
- data/lib/committee/middleware/options/base.rb +107 -0
- data/lib/committee/middleware/options/request_validation.rb +80 -0
- data/lib/committee/middleware/options/response_validation.rb +46 -0
- data/lib/committee/middleware/options.rb +12 -0
- data/lib/committee/middleware/request_validation.rb +7 -1
- data/lib/committee/middleware/response_validation.rb +6 -2
- data/lib/committee/middleware.rb +1 -0
- data/lib/committee/schema_validator/hyper_schema/response_generator.rb +1 -3
- data/lib/committee/schema_validator/hyper_schema/response_validator.rb +14 -1
- data/lib/committee/schema_validator/hyper_schema/router.rb +1 -1
- data/lib/committee/schema_validator/hyper_schema.rb +3 -14
- data/lib/committee/schema_validator/open_api_3/operation_wrapper.rb +43 -13
- data/lib/committee/schema_validator/open_api_3/parameter_deserializer.rb +556 -0
- data/lib/committee/schema_validator/open_api_3/response_validator.rb +16 -2
- data/lib/committee/schema_validator/open_api_3.rb +19 -13
- data/lib/committee/schema_validator/option.rb +6 -17
- data/lib/committee/schema_validator.rb +12 -1
- data/lib/committee/test/except_parameter.rb +416 -0
- data/lib/committee/test/methods.rb +38 -2
- data/lib/committee/version.rb +1 -1
- data/lib/committee.rb +1 -1
- data/test/drivers/open_api_2/driver_test.rb +4 -16
- data/test/drivers/open_api_2/parameter_schema_builder_test.rb +4 -50
- data/test/drivers_test.rb +35 -21
- data/test/middleware/options/base_test.rb +120 -0
- data/test/middleware/options/request_validation_test.rb +177 -0
- data/test/middleware/options/response_validation_test.rb +121 -0
- data/test/middleware/request_validation_open_api_3_test.rb +200 -80
- data/test/middleware/request_validation_test.rb +13 -70
- data/test/middleware/response_validation_open_api_3_test.rb +40 -17
- data/test/middleware/response_validation_test.rb +3 -14
- data/test/request_unpacker_test.rb +2 -10
- data/test/schema_validator/hyper_schema/parameter_coercer_test.rb +1 -37
- data/test/schema_validator/hyper_schema/request_validator_test.rb +6 -30
- data/test/schema_validator/hyper_schema/router_test.rb +5 -0
- data/test/schema_validator/hyper_schema/string_params_coercer_test.rb +1 -37
- data/test/schema_validator/open_api_3/operation_wrapper_test.rb +58 -43
- data/test/schema_validator/open_api_3/parameter_deserializer_test.rb +457 -0
- data/test/schema_validator/open_api_3/request_validator_test.rb +1 -2
- data/test/schema_validator/open_api_3/response_validator_test.rb +3 -11
- data/test/schema_validator_test.rb +41 -0
- data/test/test/methods_test.rb +238 -105
- data/test/test/schema_coverage_test.rb +8 -155
- metadata +11 -1
|
@@ -11,11 +11,7 @@ describe Committee::SchemaValidator::HyperSchema::RequestValidator do
|
|
|
11
11
|
@schema.expand_references!
|
|
12
12
|
# POST /apps/:id
|
|
13
13
|
@link = @schema.properties["app"].links[0]
|
|
14
|
-
@request = Rack::Request.new({
|
|
15
|
-
"CONTENT_TYPE" => "application/json",
|
|
16
|
-
"rack.input" => StringIO.new("{}"),
|
|
17
|
-
"REQUEST_METHOD" => "POST"
|
|
18
|
-
})
|
|
14
|
+
@request = Rack::Request.new({ "CONTENT_TYPE" => "application/json", "rack.input" => StringIO.new("{}"), "REQUEST_METHOD" => "POST" })
|
|
19
15
|
end
|
|
20
16
|
|
|
21
17
|
it "passes through a valid request with Content-Type options" do
|
|
@@ -29,22 +25,14 @@ describe Committee::SchemaValidator::HyperSchema::RequestValidator do
|
|
|
29
25
|
end
|
|
30
26
|
|
|
31
27
|
it "passes through a valid request with Content-Type options" do
|
|
32
|
-
@request =
|
|
33
|
-
Rack::Request.new({
|
|
34
|
-
"CONTENT_TYPE" => "application/json; charset=utf-8",
|
|
35
|
-
"rack.input" => StringIO.new("{}"),
|
|
36
|
-
})
|
|
28
|
+
@request = Rack::Request.new({ "CONTENT_TYPE" => "application/json; charset=utf-8", "rack.input" => StringIO.new("{}"), })
|
|
37
29
|
data = { "name" => "heroku-api", }
|
|
38
30
|
call(data)
|
|
39
31
|
end
|
|
40
32
|
|
|
41
33
|
it "detects an invalid request Content-Type" do
|
|
42
34
|
e = assert_raises(Committee::InvalidRequest) {
|
|
43
|
-
@request =
|
|
44
|
-
Rack::Request.new({
|
|
45
|
-
"CONTENT_TYPE" => "application/x-www-form-urlencoded",
|
|
46
|
-
"rack.input" => StringIO.new("{}"),
|
|
47
|
-
})
|
|
35
|
+
@request = Rack::Request.new({ "CONTENT_TYPE" => "application/x-www-form-urlencoded", "rack.input" => StringIO.new("{}"), })
|
|
48
36
|
call({})
|
|
49
37
|
}
|
|
50
38
|
message = %{"Content-Type" request header must be set to "application/json".}
|
|
@@ -52,11 +40,7 @@ describe Committee::SchemaValidator::HyperSchema::RequestValidator do
|
|
|
52
40
|
end
|
|
53
41
|
|
|
54
42
|
it "allows skipping content_type check" do
|
|
55
|
-
@request =
|
|
56
|
-
Rack::Request.new({
|
|
57
|
-
"CONTENT_TYPE" => "application/x-www-form-urlencoded",
|
|
58
|
-
"rack.input" => StringIO.new("{}"),
|
|
59
|
-
})
|
|
43
|
+
@request = Rack::Request.new({ "CONTENT_TYPE" => "application/x-www-form-urlencoded", "rack.input" => StringIO.new("{}"), })
|
|
60
44
|
call({}, {}, check_content_type: false)
|
|
61
45
|
end
|
|
62
46
|
|
|
@@ -73,11 +57,7 @@ describe Committee::SchemaValidator::HyperSchema::RequestValidator do
|
|
|
73
57
|
end
|
|
74
58
|
|
|
75
59
|
it "allows an invalid Content-Type with an empty body" do
|
|
76
|
-
@request =
|
|
77
|
-
Rack::Request.new({
|
|
78
|
-
"CONTENT_TYPE" => "application/x-www-form-urlencoded",
|
|
79
|
-
"rack.input" => StringIO.new(""),
|
|
80
|
-
})
|
|
60
|
+
@request = Rack::Request.new({ "CONTENT_TYPE" => "application/x-www-form-urlencoded", "rack.input" => StringIO.new(""), })
|
|
81
61
|
call({})
|
|
82
62
|
end
|
|
83
63
|
|
|
@@ -103,11 +83,7 @@ describe Committee::SchemaValidator::HyperSchema::RequestValidator do
|
|
|
103
83
|
before do
|
|
104
84
|
@schema = open_api_2_schema
|
|
105
85
|
@link = @schema.routes['GET'][0][1]
|
|
106
|
-
@request = Rack::Request.new({
|
|
107
|
-
"CONTENT_TYPE" => "application/json",
|
|
108
|
-
"rack.input" => StringIO.new("{}"),
|
|
109
|
-
"REQUEST_METHOD" => "POST"
|
|
110
|
-
})
|
|
86
|
+
@request = Rack::Request.new({ "CONTENT_TYPE" => "application/json", "rack.input" => StringIO.new("{}"), "REQUEST_METHOD" => "POST" })
|
|
111
87
|
end
|
|
112
88
|
|
|
113
89
|
it "passes through a valid request" do
|
|
@@ -43,6 +43,11 @@ describe Committee::SchemaValidator::HyperSchema::Router do
|
|
|
43
43
|
refute_nil link
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
+
it "does not include a similar prefix path segment" do
|
|
47
|
+
link, _ = hyper_schema_router(prefix: "/kpi").includes?("/kpi2/apps")
|
|
48
|
+
assert_nil link
|
|
49
|
+
end
|
|
50
|
+
|
|
46
51
|
it "provides named parameters" do
|
|
47
52
|
link, param_matches = open_api_2_router.find_link("GET", "/api/pets/fido")
|
|
48
53
|
refute_nil link
|
|
@@ -53,43 +53,7 @@ describe Committee::SchemaValidator::HyperSchema::StringParamsCoercer do
|
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
it "pass array property" do
|
|
56
|
-
params = {
|
|
57
|
-
"array_property" => [
|
|
58
|
-
{
|
|
59
|
-
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
|
60
|
-
"per_page" => "1",
|
|
61
|
-
"nested_coercer_object" => {
|
|
62
|
-
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
|
63
|
-
"threshold" => "1.5"
|
|
64
|
-
},
|
|
65
|
-
"nested_no_coercer_object" => {
|
|
66
|
-
"per_page" => "1",
|
|
67
|
-
"threshold" => "1.5"
|
|
68
|
-
},
|
|
69
|
-
"nested_coercer_array" => [
|
|
70
|
-
{
|
|
71
|
-
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
|
72
|
-
"threshold" => "1.5"
|
|
73
|
-
}
|
|
74
|
-
],
|
|
75
|
-
"nested_no_coercer_array" => [
|
|
76
|
-
{
|
|
77
|
-
"per_page" => "1",
|
|
78
|
-
"threshold" => "1.5"
|
|
79
|
-
}
|
|
80
|
-
]
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
|
84
|
-
"per_page" => "1",
|
|
85
|
-
"threshold" => "1.5"
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
"threshold" => "1.5",
|
|
89
|
-
"per_page" => "1"
|
|
90
|
-
}
|
|
91
|
-
],
|
|
92
|
-
}
|
|
56
|
+
params = { "array_property" => [{ "update_time" => "2016-04-01T16:00:00.000+09:00", "per_page" => "1", "nested_coercer_object" => { "update_time" => "2016-04-01T16:00:00.000+09:00", "threshold" => "1.5" }, "nested_no_coercer_object" => { "per_page" => "1", "threshold" => "1.5" }, "nested_coercer_array" => [{ "update_time" => "2016-04-01T16:00:00.000+09:00", "threshold" => "1.5" }], "nested_no_coercer_array" => [{ "per_page" => "1", "threshold" => "1.5" }] }, { "update_time" => "2016-04-01T16:00:00.000+09:00", "per_page" => "1", "threshold" => "1.5" }, { "threshold" => "1.5", "per_page" => "1" }], }
|
|
93
57
|
call(params, coerce_recursive: true)
|
|
94
58
|
|
|
95
59
|
first_data = params["array_property"][0]
|
|
@@ -18,13 +18,7 @@ describe Committee::SchemaValidator::OpenAPI3::OperationWrapper do
|
|
|
18
18
|
|
|
19
19
|
HEADER = { 'Content-Type' => 'application/json' }
|
|
20
20
|
|
|
21
|
-
SCHEMA_PROPERTIES_PAIR = [
|
|
22
|
-
['string', 'str'],
|
|
23
|
-
['integer', 1],
|
|
24
|
-
['boolean', true],
|
|
25
|
-
['boolean', false],
|
|
26
|
-
['number', 0.1],
|
|
27
|
-
]
|
|
21
|
+
SCHEMA_PROPERTIES_PAIR = [['string', 'str'], ['integer', 1], ['boolean', true], ['boolean', false], ['number', 0.1],]
|
|
28
22
|
|
|
29
23
|
it 'correct data' do
|
|
30
24
|
operation_object.validate_request_params({}, {}, SCHEMA_PROPERTIES_PAIR.to_h, HEADER, @validator_option)
|
|
@@ -32,20 +26,7 @@ describe Committee::SchemaValidator::OpenAPI3::OperationWrapper do
|
|
|
32
26
|
end
|
|
33
27
|
|
|
34
28
|
it 'correct object data' do
|
|
35
|
-
operation_object.validate_request_params(
|
|
36
|
-
{},
|
|
37
|
-
{},
|
|
38
|
-
{
|
|
39
|
-
"object_1" =>
|
|
40
|
-
{
|
|
41
|
-
"string_1" => nil,
|
|
42
|
-
"integer_1" => nil,
|
|
43
|
-
"boolean_1" => nil,
|
|
44
|
-
"number_1" => nil
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
HEADER,
|
|
48
|
-
@validator_option)
|
|
29
|
+
operation_object.validate_request_params({}, {}, { "object_1" => { "string_1" => nil, "integer_1" => nil, "boolean_1" => nil, "number_1" => nil } }, HEADER, @validator_option)
|
|
49
30
|
|
|
50
31
|
assert true
|
|
51
32
|
end
|
|
@@ -93,21 +74,9 @@ describe Committee::SchemaValidator::OpenAPI3::OperationWrapper do
|
|
|
93
74
|
end
|
|
94
75
|
|
|
95
76
|
it 'correct' do
|
|
96
|
-
operation_object.validate_request_params(
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
{},
|
|
100
|
-
HEADER,
|
|
101
|
-
@validator_option
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
operation_object.validate_request_params(
|
|
105
|
-
{},
|
|
106
|
-
{ "query_string" => "query", "query_integer_list" => [1, 2], "optional_integer" => 1 },
|
|
107
|
-
{},
|
|
108
|
-
HEADER,
|
|
109
|
-
@validator_option
|
|
110
|
-
)
|
|
77
|
+
operation_object.validate_request_params({}, { "query_string" => "query", "query_integer_list" => [1, 2] }, {}, HEADER, @validator_option)
|
|
78
|
+
|
|
79
|
+
operation_object.validate_request_params({}, { "query_string" => "query", "query_integer_list" => [1, 2], "optional_integer" => 1 }, {}, HEADER, @validator_option)
|
|
111
80
|
|
|
112
81
|
assert true
|
|
113
82
|
end
|
|
@@ -123,13 +92,7 @@ describe Committee::SchemaValidator::OpenAPI3::OperationWrapper do
|
|
|
123
92
|
|
|
124
93
|
it 'invalid type' do
|
|
125
94
|
e = assert_raises(Committee::InvalidRequest) {
|
|
126
|
-
operation_object.validate_request_params(
|
|
127
|
-
{},
|
|
128
|
-
{ "query_string" => 1, "query_integer_list" => [1, 2], "optional_integer" => 1 },
|
|
129
|
-
{},
|
|
130
|
-
HEADER,
|
|
131
|
-
@validator_option
|
|
132
|
-
)
|
|
95
|
+
operation_object.validate_request_params({}, { "query_string" => 1, "query_integer_list" => [1, 2], "optional_integer" => 1 }, {}, HEADER, @validator_option)
|
|
133
96
|
}
|
|
134
97
|
|
|
135
98
|
assert_match(/expected string, but received Integer: 1/i, e.message)
|
|
@@ -208,5 +171,57 @@ describe Committee::SchemaValidator::OpenAPI3::OperationWrapper do
|
|
|
208
171
|
assert_equal [], operation_object.request_content_types
|
|
209
172
|
end
|
|
210
173
|
end
|
|
174
|
+
|
|
175
|
+
describe 'coercion option wiring' do
|
|
176
|
+
before do
|
|
177
|
+
@path = '/coerce_path_params/1'
|
|
178
|
+
@method = 'get'
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
it 'uses coerce_path_params for explicit path coercion' do
|
|
182
|
+
disabled = Committee::SchemaValidator::Option.new({ coerce_path_params: false, coerce_query_params: true }, open_api_3_schema, :open_api_3)
|
|
183
|
+
enabled = Committee::SchemaValidator::Option.new({ coerce_path_params: true, coerce_query_params: false }, open_api_3_schema, :open_api_3)
|
|
184
|
+
|
|
185
|
+
error = assert_raises(Committee::InvalidRequest) do
|
|
186
|
+
operation_object.coerce_path_parameter(disabled)
|
|
187
|
+
end
|
|
188
|
+
assert_match(/expected integer, but received String: "1"/i, error.message)
|
|
189
|
+
|
|
190
|
+
coerced = operation_object.coerce_path_parameter(enabled)
|
|
191
|
+
assert_kind_of(Integer, coerced['integer'])
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
it 'uses coerce_query_params for request parameter validation' do
|
|
195
|
+
query_coercion_disabled = Committee::SchemaValidator::Option.new({ coerce_query_params: false }, open_api_3_schema, :open_api_3)
|
|
196
|
+
query_coercion_enabled = Committee::SchemaValidator::Option.new({ coerce_query_params: true }, open_api_3_schema, :open_api_3)
|
|
197
|
+
|
|
198
|
+
error = assert_raises(Committee::InvalidRequest) do
|
|
199
|
+
@path = '/characters'
|
|
200
|
+
operation_object.validate_request_params({}, { "limit" => "1" }, {}, HEADER, query_coercion_disabled)
|
|
201
|
+
end
|
|
202
|
+
assert_match(/expected integer, but received String: "1"/i, error.message)
|
|
203
|
+
|
|
204
|
+
@path = '/characters'
|
|
205
|
+
operation_object.validate_request_params({}, { "limit" => "1" }, {}, HEADER, query_coercion_enabled)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
it 'uses coerce_form_params for JSON request bodies too' do
|
|
209
|
+
@path = '/validate'
|
|
210
|
+
@method = 'post'
|
|
211
|
+
|
|
212
|
+
body_coercion_disabled = Committee::SchemaValidator::Option.new({ coerce_form_params: false }, open_api_3_schema, :open_api_3)
|
|
213
|
+
body_coercion_enabled = Committee::SchemaValidator::Option.new({ coerce_form_params: true }, open_api_3_schema, :open_api_3)
|
|
214
|
+
|
|
215
|
+
error = assert_raises(Committee::InvalidRequest) do
|
|
216
|
+
operation_object.validate_request_params({}, {}, { "integer" => "1" }, HEADER, body_coercion_disabled)
|
|
217
|
+
end
|
|
218
|
+
assert_match(/expected integer, but received String: "1"/i, error.message)
|
|
219
|
+
|
|
220
|
+
body_params = { "integer" => "1" }
|
|
221
|
+
operation_object.validate_request_params({}, {}, body_params, HEADER, body_coercion_enabled)
|
|
222
|
+
|
|
223
|
+
assert_kind_of(Integer, body_params["integer"])
|
|
224
|
+
end
|
|
225
|
+
end
|
|
211
226
|
end
|
|
212
227
|
end
|