openapi_parser 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +5 -2
- data/.rubocop_ignore.yml +6 -0
- data/.travis.yml +33 -4
- data/CHANGELOG.md +9 -0
- data/README.md +39 -6
- data/lib/openapi_parser/concern.rb +2 -1
- data/lib/openapi_parser/concerns/expandable.rb +52 -44
- data/lib/openapi_parser/concerns/media_type_selectable.rb +26 -0
- data/lib/openapi_parser/concerns/parser.rb +43 -0
- data/lib/openapi_parser/concerns/parser/core.rb +21 -0
- data/lib/openapi_parser/concerns/parser/hash.rb +10 -0
- data/lib/openapi_parser/concerns/parser/hash_body.rb +12 -0
- data/lib/openapi_parser/concerns/parser/list.rb +10 -0
- data/lib/openapi_parser/concerns/parser/object.rb +14 -0
- data/lib/openapi_parser/concerns/parser/value.rb +14 -0
- data/lib/openapi_parser/concerns/schema_loader.rb +58 -0
- data/lib/openapi_parser/concerns/schema_loader/base.rb +28 -0
- data/lib/openapi_parser/concerns/schema_loader/creator.rb +48 -0
- data/lib/openapi_parser/concerns/schema_loader/hash_body_loader.rb +37 -0
- data/lib/openapi_parser/concerns/schema_loader/hash_objects_loader.rb +29 -0
- data/lib/openapi_parser/concerns/schema_loader/list_loader.rb +28 -0
- data/lib/openapi_parser/concerns/schema_loader/objects_loader.rb +21 -0
- data/lib/openapi_parser/concerns/schema_loader/values_loader.rb +10 -0
- data/lib/openapi_parser/config.rb +1 -1
- data/lib/openapi_parser/errors.rb +9 -0
- data/lib/openapi_parser/path_item_finder.rb +18 -18
- data/lib/openapi_parser/request_operation.rb +4 -4
- data/lib/openapi_parser/schema_validator.rb +77 -54
- data/lib/openapi_parser/schema_validators/all_of_validator.rb +16 -0
- data/lib/openapi_parser/schema_validators/any_of_validator.rb +1 -1
- data/lib/openapi_parser/schema_validators/array_validator.rb +2 -4
- data/lib/openapi_parser/schema_validators/base.rb +9 -6
- data/lib/openapi_parser/schema_validators/boolean_validator.rb +11 -9
- data/lib/openapi_parser/schema_validators/float_validator.rb +8 -10
- data/lib/openapi_parser/schema_validators/integer_validator.rb +11 -10
- data/lib/openapi_parser/schema_validators/nil_validator.rb +1 -0
- data/lib/openapi_parser/schema_validators/object_validator.rb +3 -3
- data/lib/openapi_parser/schema_validators/string_validator.rb +13 -13
- data/lib/openapi_parser/schemas/base.rb +1 -2
- data/lib/openapi_parser/schemas/media_type.rb +3 -1
- data/lib/openapi_parser/schemas/openapi.rb +1 -1
- data/lib/openapi_parser/schemas/operation.rb +17 -14
- data/lib/openapi_parser/schemas/parameter.rb +2 -2
- data/lib/openapi_parser/schemas/request_body.rb +12 -5
- data/lib/openapi_parser/schemas/response.rb +4 -4
- data/lib/openapi_parser/schemas/responses.rb +21 -3
- data/lib/openapi_parser/version.rb +1 -1
- data/openapi_parser.gemspec +3 -2
- metadata +51 -19
- data/lib/openapi_parser/concerns/parseable.rb +0 -238
@@ -0,0 +1,16 @@
|
|
1
|
+
# validate AllOf schema
|
2
|
+
class OpenAPIParser::SchemaValidator
|
3
|
+
class AllOfValidator < Base
|
4
|
+
# coerce and validate value
|
5
|
+
# @param [Object] value
|
6
|
+
# @param [OpenAPIParser::Schemas::Schema] schema
|
7
|
+
def coerce_and_validate(value, schema)
|
8
|
+
# if any schema return error, it's not valida all of value
|
9
|
+
schema.all_of.each do |s|
|
10
|
+
_coerced, err = validatable.validate_schema(value, s)
|
11
|
+
return [nil, err] if err
|
12
|
+
end
|
13
|
+
[value, nil]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -5,7 +5,7 @@ class OpenAPIParser::SchemaValidator
|
|
5
5
|
def coerce_and_validate(value, schema)
|
6
6
|
# in all schema return error (=true) not any of data
|
7
7
|
schema.any_of.each do |s|
|
8
|
-
coerced, err =
|
8
|
+
coerced, err = validatable.validate_schema(value, s)
|
9
9
|
return [coerced, nil] if err.nil?
|
10
10
|
end
|
11
11
|
[nil, OpenAPIParser::NotAnyOf.new(value, schema.object_reference)]
|
@@ -1,17 +1,15 @@
|
|
1
1
|
class OpenAPIParser::SchemaValidator
|
2
2
|
class ArrayValidator < Base
|
3
|
-
|
4
3
|
# @param [Array] value
|
5
4
|
# @param [OpenAPIParser::Schemas::Schema] schema
|
6
5
|
def coerce_and_validate(value, schema)
|
7
|
-
return
|
6
|
+
return OpenAPIParser::ValidateError.build_error_result(value, schema) unless value.kind_of?(Array)
|
8
7
|
|
9
8
|
# array type have an schema in items property
|
10
9
|
items_schema = schema.items
|
11
10
|
|
12
|
-
|
13
11
|
coerced_values = value.map do |v|
|
14
|
-
coerced, err =
|
12
|
+
coerced, err = validatable.validate_schema(v, items_schema)
|
15
13
|
return [nil, err] if err
|
16
14
|
|
17
15
|
coerced
|
@@ -1,16 +1,19 @@
|
|
1
1
|
class OpenAPIParser::SchemaValidator
|
2
2
|
class Base
|
3
|
-
|
4
|
-
|
3
|
+
# @param [OpenAPIParser::SchemaValidator::Validatable] validatable
|
4
|
+
def initialize(validatable, coerce_value)
|
5
|
+
@validatable = validatable
|
5
6
|
@coerce_value = coerce_value
|
6
7
|
end
|
7
8
|
|
8
|
-
attr_reader :
|
9
|
+
attr_reader :validatable
|
9
10
|
|
10
|
-
# @!attribute [r]
|
11
|
-
# @return [OpenAPIParser::SchemaValidator]
|
11
|
+
# @!attribute [r] validatable
|
12
|
+
# @return [OpenAPIParser::SchemaValidator::Validatable]
|
12
13
|
|
13
|
-
#
|
14
|
+
# need override
|
15
|
+
# @param [Array] _value
|
16
|
+
# @param [OpenAPIParser::Schemas::Schema] _schema
|
14
17
|
def coerce_and_validate(_value, _schema)
|
15
18
|
raise 'need implement'
|
16
19
|
end
|
@@ -1,22 +1,24 @@
|
|
1
1
|
class OpenAPIParser::SchemaValidator
|
2
2
|
class BooleanValidator < Base
|
3
|
+
TRUE_VALUES = ['true', '1'].freeze
|
4
|
+
FALSE_VALUES = ['false', '0'].freeze
|
5
|
+
|
3
6
|
def coerce_and_validate(value, schema)
|
4
7
|
value = coerce(value) if @coerce_value
|
5
8
|
|
6
|
-
return
|
9
|
+
return OpenAPIParser::ValidateError.build_error_result(value, schema) unless value.kind_of?(TrueClass) || value.kind_of?(FalseClass)
|
10
|
+
|
7
11
|
[value, nil]
|
8
12
|
end
|
9
13
|
|
10
14
|
private
|
11
15
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
def coerce(value)
|
17
|
+
return true if TRUE_VALUES.include?(value)
|
18
|
+
|
19
|
+
return false if FALSE_VALUES.include?(value)
|
20
|
+
|
21
|
+
value
|
18
22
|
end
|
19
|
-
value
|
20
|
-
end
|
21
23
|
end
|
22
24
|
end
|
@@ -5,25 +5,23 @@ class OpenAPIParser::SchemaValidator
|
|
5
5
|
def coerce_and_validate(value, schema)
|
6
6
|
value = coerce(value) if @coerce_value
|
7
7
|
|
8
|
-
return
|
8
|
+
return OpenAPIParser::ValidateError.build_error_result(value, schema) if value.kind_of?(Integer)
|
9
|
+
|
9
10
|
coercer_and_validate_numeric(value, schema)
|
10
11
|
end
|
11
12
|
|
12
13
|
private
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
check_enum_include(value, schema)
|
17
|
-
end
|
15
|
+
def coercer_and_validate_numeric(value, schema)
|
16
|
+
return OpenAPIParser::ValidateError.build_error_result(value, schema) unless value.kind_of?(Numeric)
|
18
17
|
|
19
|
-
|
18
|
+
check_enum_include(value, schema)
|
19
|
+
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
return Float(value)
|
21
|
+
def coerce(value)
|
22
|
+
Float(value)
|
24
23
|
rescue ArgumentError => e
|
25
24
|
raise e unless e.message =~ /invalid value for Float/
|
26
25
|
end
|
27
|
-
end
|
28
26
|
end
|
29
27
|
end
|
@@ -5,22 +5,23 @@ class OpenAPIParser::SchemaValidator
|
|
5
5
|
def coerce_and_validate(value, schema)
|
6
6
|
value = coerce(value) if @coerce_value
|
7
7
|
|
8
|
-
return
|
8
|
+
return OpenAPIParser::ValidateError.build_error_result(value, schema) unless value.kind_of?(Integer)
|
9
|
+
|
9
10
|
check_enum_include(value, schema)
|
10
11
|
end
|
11
12
|
|
12
13
|
private
|
13
14
|
|
14
|
-
|
15
|
-
|
15
|
+
def coerce(value)
|
16
|
+
return value if value.kind_of?(Integer)
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
begin
|
19
|
+
return Integer(value)
|
20
|
+
rescue ArgumentError => e
|
21
|
+
raise e unless e.message =~ /invalid value for Integer/
|
22
|
+
end
|
22
23
|
|
23
|
-
|
24
|
-
|
24
|
+
value
|
25
|
+
end
|
25
26
|
end
|
26
27
|
end
|
@@ -1,17 +1,17 @@
|
|
1
1
|
class OpenAPIParser::SchemaValidator
|
2
2
|
class ObjectValidator < Base
|
3
|
-
|
4
3
|
# @param [Hash] value
|
5
4
|
# @param [OpenAPIParser::Schemas::Schema] schema
|
6
5
|
def coerce_and_validate(value, schema)
|
7
|
-
return
|
6
|
+
return OpenAPIParser::ValidateError.build_error_result(value, schema) unless value.kind_of?(Hash)
|
8
7
|
|
9
8
|
return [value, nil] unless schema.properties
|
9
|
+
|
10
10
|
required_set = schema.required ? schema.required.to_set : Set.new
|
11
11
|
|
12
12
|
coerced_values = value.map do |name, v|
|
13
13
|
s = schema.properties[name]
|
14
|
-
coerced, err =
|
14
|
+
coerced, err = validatable.validate_schema(v, s)
|
15
15
|
return [nil, err] if err
|
16
16
|
|
17
17
|
required_set.delete(name)
|
@@ -8,7 +8,7 @@ class OpenAPIParser::SchemaValidator
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def coerce_and_validate(value, schema)
|
11
|
-
return
|
11
|
+
return OpenAPIParser::ValidateError.build_error_result(value, schema) unless value.kind_of?(String)
|
12
12
|
|
13
13
|
value, err = check_enum_include(value, schema)
|
14
14
|
return [nil, err] if err
|
@@ -20,19 +20,19 @@ class OpenAPIParser::SchemaValidator
|
|
20
20
|
|
21
21
|
private
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
def parse_date_time(value)
|
29
|
-
begin
|
30
|
-
return @datetime_coerce_class.parse(value)
|
31
|
-
rescue ArgumentError => e
|
32
|
-
raise e unless e.message =~ /invalid date/
|
23
|
+
# @param [OpenAPIParser::Schemas::Schema] schema
|
24
|
+
def coerce_date_time(value, schema)
|
25
|
+
(schema.format == 'date-time') ? parse_date_time(value) : value
|
33
26
|
end
|
34
27
|
|
35
|
-
value
|
36
|
-
|
28
|
+
def parse_date_time(value)
|
29
|
+
begin
|
30
|
+
return @datetime_coerce_class.parse(value)
|
31
|
+
rescue ArgumentError => e
|
32
|
+
raise e unless e.message =~ /invalid date/
|
33
|
+
end
|
34
|
+
|
35
|
+
value
|
36
|
+
end
|
37
37
|
end
|
38
38
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module OpenAPIParser::Schemas
|
2
2
|
class Base
|
3
|
-
include OpenAPIParser::
|
3
|
+
include OpenAPIParser::Parser
|
4
4
|
include OpenAPIParser::Findable
|
5
5
|
include OpenAPIParser::Expandable
|
6
6
|
|
@@ -19,7 +19,6 @@ module OpenAPIParser::Schemas
|
|
19
19
|
|
20
20
|
# override
|
21
21
|
def after_init
|
22
|
-
|
23
22
|
end
|
24
23
|
|
25
24
|
def inspect
|
@@ -5,10 +5,12 @@
|
|
5
5
|
module OpenAPIParser::Schemas
|
6
6
|
class MediaType < Base
|
7
7
|
# @!attribute [r] schema
|
8
|
-
# @return [Schema, nil]
|
8
|
+
# @return [Schema, nil] OpenAPI3 Schema object
|
9
9
|
openapi_attr_object :schema, Schema, reference: true
|
10
10
|
|
11
|
+
# validate params by schema definitions
|
11
12
|
# @param [Hash] params
|
13
|
+
# @param [OpenAPIParser::SchemaValidator::Options] options
|
12
14
|
def validate_parameter(params, options)
|
13
15
|
OpenAPIParser::SchemaValidator.validate(params, schema, options)
|
14
16
|
end
|
@@ -8,7 +8,7 @@ module OpenAPIParser::Schemas
|
|
8
8
|
def initialize(raw_schema, config)
|
9
9
|
super('#', nil, self, raw_schema)
|
10
10
|
@find_object_cache = {}
|
11
|
-
@path_item_finder = OpenAPIParser::PathItemFinder.new(paths)
|
11
|
+
@path_item_finder = OpenAPIParser::PathItemFinder.new(paths) if paths # invalid definition
|
12
12
|
@config = config
|
13
13
|
end
|
14
14
|
|
@@ -12,15 +12,18 @@ module OpenAPIParser::Schemas
|
|
12
12
|
openapi_attr_list_object :parameters, Parameter, reference: true
|
13
13
|
|
14
14
|
# @!attribute [r] request_body
|
15
|
-
# @return [OpenAPIParser::Schemas::RequestBody, nil]
|
15
|
+
# @return [OpenAPIParser::Schemas::RequestBody, nil] return OpenAPI3 object
|
16
16
|
openapi_attr_object :request_body, RequestBody, reference: true, schema_key: :requestBody
|
17
17
|
|
18
|
+
# @!attribute [r] responses
|
19
|
+
# @return [OpenAPIParser::Schemas::Responses, nil] return OpenAPI3 object
|
18
20
|
openapi_attr_object :responses, Responses, reference: false
|
19
21
|
|
20
22
|
def validate_request_body(content_type, params, options)
|
21
23
|
request_body&.validate_request_body(content_type, params, options)
|
22
24
|
end
|
23
25
|
|
26
|
+
# @param [Integer] status_code
|
24
27
|
def validate_response_body(status_code, content_type, data)
|
25
28
|
responses&.validate_response_body(status_code, content_type, data)
|
26
29
|
end
|
@@ -36,18 +39,18 @@ module OpenAPIParser::Schemas
|
|
36
39
|
|
37
40
|
private
|
38
41
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
42
|
+
def path_parameter_hash
|
43
|
+
@path_parameter_hash ||= (parameters || []).
|
44
|
+
select(&:in_path?).
|
45
|
+
map { |param| [param.name, param] }.
|
46
|
+
to_h
|
47
|
+
end
|
48
|
+
|
49
|
+
def query_parameter_hash
|
50
|
+
@query_parameter_hash ||= (parameters || []).
|
51
|
+
select(&:in_query?).
|
52
|
+
map { |param| [param.name, param] }.
|
53
|
+
to_h
|
54
|
+
end
|
52
55
|
end
|
53
56
|
end
|
@@ -12,11 +12,11 @@ module OpenAPIParser::Schemas
|
|
12
12
|
openapi_attr_object :schema, Schema, reference: true
|
13
13
|
|
14
14
|
def in_query?
|
15
|
-
self.in ==
|
15
|
+
self.in == 'query'
|
16
16
|
end
|
17
17
|
|
18
18
|
def in_path?
|
19
|
-
self.in ==
|
19
|
+
self.in == 'path'
|
20
20
|
end
|
21
21
|
|
22
22
|
# @return [Object] coerced or original params
|
@@ -2,16 +2,23 @@
|
|
2
2
|
|
3
3
|
module OpenAPIParser::Schemas
|
4
4
|
class RequestBody < Base
|
5
|
+
include OpenAPIParser::MediaTypeSelectable
|
6
|
+
|
7
|
+
# @!attribute [r] description
|
8
|
+
# @return [String] description data
|
9
|
+
# @!attribute [r] required
|
10
|
+
# @return [Boolean] required bool data
|
5
11
|
openapi_attr_values :description, :required
|
6
12
|
|
7
13
|
# @!attribute [r] content
|
8
|
-
# @return [Hash{String => MediaType}, nil]
|
14
|
+
# @return [Hash{String => MediaType}, nil] content type to MediaType object
|
9
15
|
openapi_attr_hash_object :content, MediaType, reference: false
|
10
16
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
# @param [String] content_type
|
18
|
+
# @param [Hash] params
|
19
|
+
# @param [OpenAPIParser::SchemaValidator::Options] options
|
20
|
+
def validate_request_body(content_type, params, options)
|
21
|
+
media_type = select_media_type(content_type, content)
|
15
22
|
return params unless media_type
|
16
23
|
|
17
24
|
media_type.validate_parameter(params, options)
|
@@ -3,16 +3,16 @@
|
|
3
3
|
|
4
4
|
module OpenAPIParser::Schemas
|
5
5
|
class Response < Base
|
6
|
+
include OpenAPIParser::MediaTypeSelectable
|
7
|
+
|
6
8
|
openapi_attr_values :description
|
7
9
|
|
8
10
|
# @!attribute [r] content
|
9
|
-
# @return [Hash{String => MediaType}, nil]
|
11
|
+
# @return [Hash{String => MediaType}, nil] content_type to MediaType hash
|
10
12
|
openapi_attr_hash_object :content, MediaType, reference: false
|
11
13
|
|
12
14
|
def validate_parameter(content_type, params)
|
13
|
-
|
14
|
-
|
15
|
-
media_type = content[content_type]
|
15
|
+
media_type = select_media_type(content_type, content)
|
16
16
|
return nil unless media_type
|
17
17
|
|
18
18
|
options = ::OpenAPIParser::SchemaValidator::Options.new # response validator not support any options
|
@@ -3,22 +3,40 @@
|
|
3
3
|
module OpenAPIParser::Schemas
|
4
4
|
class Responses < Base
|
5
5
|
# @!attribute [r] default
|
6
|
-
# @return [Response, Reference, nil]
|
6
|
+
# @return [Response, Reference, nil] default response object
|
7
7
|
openapi_attr_object :default, Response, reference: true
|
8
8
|
|
9
9
|
# @!attribute [r] response
|
10
|
-
# @return [Hash{String => Response, Reference}, nil]
|
10
|
+
# @return [Hash{String => Response, Reference}, nil] response object indexed by status code. see: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#patterned-fields-1
|
11
11
|
openapi_attr_hash_body_objects 'response', Response, reject_keys: [:default], allow_reference: true, allow_data_type: false
|
12
12
|
|
13
|
+
# validate params data by definition
|
14
|
+
# find response object by status_code and content_type
|
15
|
+
# https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#patterned-fields-1
|
16
|
+
# @param [Integer] status_code
|
17
|
+
# @param [String] content_type
|
18
|
+
# @param [Hash] params
|
13
19
|
def validate_response_body(status_code, content_type, params)
|
14
|
-
# TODO: support wildcard status code like 2XX
|
15
20
|
return nil unless response
|
16
21
|
|
17
22
|
res = response[status_code.to_s]
|
18
23
|
return res.validate_parameter(content_type, params) if res
|
19
24
|
|
25
|
+
wild_card = status_code_to_wild_card(status_code)
|
26
|
+
res = response[wild_card]
|
27
|
+
return res.validate_parameter(content_type, params) if res
|
20
28
|
|
21
29
|
default&.validate_parameter(content_type, params)
|
22
30
|
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
# parse 400 -> 4xx
|
35
|
+
# OpenAPI3 allow 1xx, 2xx, 3xx... only, don't allow 41x
|
36
|
+
# @param [Integer] status_code
|
37
|
+
def status_code_to_wild_card(status_code)
|
38
|
+
top = status_code / 100
|
39
|
+
"#{top}XX"
|
40
|
+
end
|
23
41
|
end
|
24
42
|
end
|