openapi_parser 0.1.5 → 0.1.6
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/.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
|