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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +5 -2
  3. data/.rubocop_ignore.yml +6 -0
  4. data/.travis.yml +33 -4
  5. data/CHANGELOG.md +9 -0
  6. data/README.md +39 -6
  7. data/lib/openapi_parser/concern.rb +2 -1
  8. data/lib/openapi_parser/concerns/expandable.rb +52 -44
  9. data/lib/openapi_parser/concerns/media_type_selectable.rb +26 -0
  10. data/lib/openapi_parser/concerns/parser.rb +43 -0
  11. data/lib/openapi_parser/concerns/parser/core.rb +21 -0
  12. data/lib/openapi_parser/concerns/parser/hash.rb +10 -0
  13. data/lib/openapi_parser/concerns/parser/hash_body.rb +12 -0
  14. data/lib/openapi_parser/concerns/parser/list.rb +10 -0
  15. data/lib/openapi_parser/concerns/parser/object.rb +14 -0
  16. data/lib/openapi_parser/concerns/parser/value.rb +14 -0
  17. data/lib/openapi_parser/concerns/schema_loader.rb +58 -0
  18. data/lib/openapi_parser/concerns/schema_loader/base.rb +28 -0
  19. data/lib/openapi_parser/concerns/schema_loader/creator.rb +48 -0
  20. data/lib/openapi_parser/concerns/schema_loader/hash_body_loader.rb +37 -0
  21. data/lib/openapi_parser/concerns/schema_loader/hash_objects_loader.rb +29 -0
  22. data/lib/openapi_parser/concerns/schema_loader/list_loader.rb +28 -0
  23. data/lib/openapi_parser/concerns/schema_loader/objects_loader.rb +21 -0
  24. data/lib/openapi_parser/concerns/schema_loader/values_loader.rb +10 -0
  25. data/lib/openapi_parser/config.rb +1 -1
  26. data/lib/openapi_parser/errors.rb +9 -0
  27. data/lib/openapi_parser/path_item_finder.rb +18 -18
  28. data/lib/openapi_parser/request_operation.rb +4 -4
  29. data/lib/openapi_parser/schema_validator.rb +77 -54
  30. data/lib/openapi_parser/schema_validators/all_of_validator.rb +16 -0
  31. data/lib/openapi_parser/schema_validators/any_of_validator.rb +1 -1
  32. data/lib/openapi_parser/schema_validators/array_validator.rb +2 -4
  33. data/lib/openapi_parser/schema_validators/base.rb +9 -6
  34. data/lib/openapi_parser/schema_validators/boolean_validator.rb +11 -9
  35. data/lib/openapi_parser/schema_validators/float_validator.rb +8 -10
  36. data/lib/openapi_parser/schema_validators/integer_validator.rb +11 -10
  37. data/lib/openapi_parser/schema_validators/nil_validator.rb +1 -0
  38. data/lib/openapi_parser/schema_validators/object_validator.rb +3 -3
  39. data/lib/openapi_parser/schema_validators/string_validator.rb +13 -13
  40. data/lib/openapi_parser/schemas/base.rb +1 -2
  41. data/lib/openapi_parser/schemas/media_type.rb +3 -1
  42. data/lib/openapi_parser/schemas/openapi.rb +1 -1
  43. data/lib/openapi_parser/schemas/operation.rb +17 -14
  44. data/lib/openapi_parser/schemas/parameter.rb +2 -2
  45. data/lib/openapi_parser/schemas/request_body.rb +12 -5
  46. data/lib/openapi_parser/schemas/response.rb +4 -4
  47. data/lib/openapi_parser/schemas/responses.rb +21 -3
  48. data/lib/openapi_parser/version.rb +1 -1
  49. data/openapi_parser.gemspec +3 -2
  50. metadata +51 -19
  51. 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 = validator.validate_schema(value, s)
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 validator.validate_error(value, schema) unless value.is_a?(Array)
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 = validator.validate_schema(v, items_schema)
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
- def initialize(validator, coerce_value)
4
- @validator = validator
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 :validator
9
+ attr_reader :validatable
9
10
 
10
- # @!attribute [r] validator
11
- # @return [OpenAPIParser::SchemaValidator]
11
+ # @!attribute [r] validatable
12
+ # @return [OpenAPIParser::SchemaValidator::Validatable]
12
13
 
13
- # return [coerced_value, error]
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 validator.validate_error(value, schema) unless value.is_a?(TrueClass) || value.is_a?(FalseClass)
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
- def coerce(value)
13
- if value == "true" || value == "1"
14
- return true
15
- end
16
- if value == "false" || value == "0"
17
- return false
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 validator.validate_integer(value, schema) if value.is_a?(Integer)
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
- def coercer_and_validate_numeric(value, schema)
15
- return validator.validate_error(value, schema) unless value.is_a?(Numeric)
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
- private
18
+ check_enum_include(value, schema)
19
+ end
20
20
 
21
- def coerce(value)
22
- begin
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 validator.validate_error(value, schema) unless value.is_a?(Integer)
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
- def coerce(value)
15
- return value if value.is_a?(Integer)
15
+ def coerce(value)
16
+ return value if value.kind_of?(Integer)
16
17
 
17
- begin
18
- return Integer(value)
19
- rescue ArgumentError => e
20
- raise e unless e.message =~ /invalid value for Integer/
21
- end
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
- value
24
- end
24
+ value
25
+ end
25
26
  end
26
27
  end
@@ -4,6 +4,7 @@ class OpenAPIParser::SchemaValidator
4
4
  # @param [OpenAPIParser::Schemas::Schema] schema
5
5
  def coerce_and_validate(value, schema)
6
6
  return [value, nil] if schema.nullable
7
+
7
8
  [nil, OpenAPIParser::NotNullError.new(schema.object_reference)]
8
9
  end
9
10
  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 validator.validate_error(value, schema) unless value.is_a?(Hash)
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 = validator.validate_schema(v, s)
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 validator.validate_error(value, schema) unless value.is_a?(String)
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
- # @param [OpenAPIParser::Schemas::Schema] schema
24
- def coerce_date_time(value, schema)
25
- schema.format == "date-time" ? parse_date_time(value) : value
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
- end
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::Parseable
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
- def path_parameter_hash
40
- @path_parameter_hash ||= (parameters || []).
41
- select(&:in_path?).
42
- map{ |param| [param.name, param] }.
43
- to_h
44
- end
45
-
46
- def query_parameter_hash
47
- @query_parameter_hash ||= (parameters || []).
48
- select(&:in_query?).
49
- map{ |param| [param.name, param] }.
50
- to_h
51
- end
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 == "query"
15
+ self.in == 'query'
16
16
  end
17
17
 
18
18
  def in_path?
19
- self.in == "path"
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
- def validate_request_body(_content_type, params, options)
12
- # TODO: now support application/json only :(
13
-
14
- media_type = content['application/json']
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
- # TODO: support wildcard type like application/* (OpenAPI3 definition)
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