openapi_parser 0.1.2 → 0.1.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/openapi_parser.rb +14 -3
- data/lib/openapi_parser/concern.rb +1 -0
- data/lib/openapi_parser/concerns/expandable.rb +76 -0
- data/lib/openapi_parser/concerns/findable.rb +12 -1
- data/lib/openapi_parser/concerns/parseable.rb +8 -2
- data/lib/openapi_parser/config.rb +24 -0
- data/lib/openapi_parser/errors.rb +58 -0
- data/lib/openapi_parser/parameter_validator.rb +23 -0
- data/lib/openapi_parser/path_item_finder.rb +4 -4
- data/lib/openapi_parser/reference_expander.rb +9 -0
- data/lib/openapi_parser/request_operation.rb +36 -9
- data/lib/openapi_parser/schema_validator.rb +65 -128
- data/lib/openapi_parser/schema_validators/any_of_validator.rb +14 -0
- data/lib/openapi_parser/schema_validators/array_validator.rb +25 -0
- data/lib/openapi_parser/schema_validators/base.rb +18 -0
- data/lib/openapi_parser/schema_validators/boolean_validator.rb +22 -0
- data/lib/openapi_parser/schema_validators/enumable.rb +10 -0
- data/lib/openapi_parser/schema_validators/float_validator.rb +29 -0
- data/lib/openapi_parser/schema_validators/integer_validator.rb +26 -0
- data/lib/openapi_parser/schema_validators/nil_validator.rb +10 -0
- data/lib/openapi_parser/schema_validators/object_validator.rb +28 -0
- data/lib/openapi_parser/schema_validators/options.rb +10 -0
- data/lib/openapi_parser/schema_validators/string_validator.rb +38 -0
- data/lib/openapi_parser/schemas/base.rb +1 -0
- data/lib/openapi_parser/schemas/media_type.rb +2 -2
- data/lib/openapi_parser/schemas/openapi.rb +4 -3
- data/lib/openapi_parser/schemas/operation.rb +31 -2
- data/lib/openapi_parser/schemas/parameter.rb +16 -0
- data/lib/openapi_parser/schemas/reference.rb +2 -0
- data/lib/openapi_parser/schemas/request_body.rb +3 -3
- data/lib/openapi_parser/schemas/response.rb +10 -0
- data/lib/openapi_parser/schemas/responses.rb +11 -0
- data/lib/openapi_parser/version.rb +1 -1
- data/openapi_parser.gemspec +1 -0
- metadata +32 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: ddf9e2711b22d6b164e2bccd23ec3d06a2bd66918b61213a2f0d5c84eb0f5fa5
         | 
| 4 | 
            +
              data.tar.gz: 908dc71a0e892164a987968587c0a4899e91207c27bbd8a4e65d27b517398d8e
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 1e38fba425316e75580b5dbfd2f2e012890e4d4d9ad9e0abd83f74c8500176d21b1ddee533cf9120accd9355e60b8d5307fb3913d9678d6e3239c9fcbb3727f1
         | 
| 7 | 
            +
              data.tar.gz: a7e22a6b8248fb0931c396ba1a8b07b8f9cea6a7e0f6832a1a2b1af4eba82bf673357044d9d0f8bb0c9c5bf5929106d47356e97411412bab60ef5fcc5efac703
         | 
    
        data/lib/openapi_parser.rb
    CHANGED
    
    | @@ -1,15 +1,26 @@ | |
| 1 | 
            +
            require 'time'
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            require 'openapi_parser/version'
         | 
| 4 | 
            +
            require 'openapi_parser/config'
         | 
| 5 | 
            +
            require 'openapi_parser/errors'
         | 
| 2 6 | 
             
            require 'openapi_parser/concern'
         | 
| 3 7 | 
             
            require 'openapi_parser/schemas'
         | 
| 4 8 | 
             
            require 'openapi_parser/path_item_finder'
         | 
| 5 9 | 
             
            require 'openapi_parser/request_operation'
         | 
| 6 10 | 
             
            require 'openapi_parser/schema_validator'
         | 
| 11 | 
            +
            require 'openapi_parser/parameter_validator'
         | 
| 12 | 
            +
            require 'openapi_parser/reference_expander'
         | 
| 7 13 |  | 
| 8 14 | 
             
            module OpenAPIParser
         | 
| 9 15 | 
             
              class << self
         | 
| 10 | 
            -
                # @ | 
| 11 | 
            -
                def parse(schema)
         | 
| 12 | 
            -
                   | 
| 16 | 
            +
                # @return [OpenAPIParser::Schemas::OpenAPI]
         | 
| 17 | 
            +
                def parse(schema, config = {})
         | 
| 18 | 
            +
                  c = Config.new(config)
         | 
| 19 | 
            +
                  root = Schemas::OpenAPI.new(schema, c)
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  OpenAPIParser::ReferenceExpander.expand(root) if c.expand_reference
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  root
         | 
| 13 24 | 
             
                end
         | 
| 14 25 | 
             
              end
         | 
| 15 26 | 
             
            end
         | 
| @@ -0,0 +1,76 @@ | |
| 1 | 
            +
            module OpenAPIParser::Expandable
         | 
| 2 | 
            +
              def expand_reference(root)
         | 
| 3 | 
            +
                expand_list_objects(root, self.class._openapi_attr_list_objects&.keys)
         | 
| 4 | 
            +
                expand_objects(root, self.class._openapi_attr_objects&.keys)
         | 
| 5 | 
            +
                expand_hash_objects(root, self.class._openapi_attr_hash_objects&.keys)
         | 
| 6 | 
            +
                expand_hash_objects(root, self.class._openapi_attr_hash_body_objects&.keys)
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              private
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              def expand_hash_objects(root, attribute_names)
         | 
| 12 | 
            +
                return unless attribute_names
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                attribute_names.each do |name|
         | 
| 15 | 
            +
                  h = send(name)
         | 
| 16 | 
            +
                  next if h.nil?
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  update_values = h.map do |k, v|
         | 
| 19 | 
            +
                    next [k, referenced_object(root, v)] if v.is_a?(OpenAPIParser::Schemas::Reference)
         | 
| 20 | 
            +
                    v.expand_reference(root) if v.is_a?(OpenAPIParser::Expandable)
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    nil
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  update_values.compact.each do |k, v|
         | 
| 26 | 
            +
                    _update_child_object(h[k], v)
         | 
| 27 | 
            +
                    h[k] = v
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              def expand_objects(root, attribute_names)
         | 
| 33 | 
            +
                return unless attribute_names
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                attribute_names.each do |name|
         | 
| 36 | 
            +
                  v = send(name)
         | 
| 37 | 
            +
                  next if v.nil?
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  if v.is_a?(OpenAPIParser::Schemas::Reference)
         | 
| 40 | 
            +
                    obj = referenced_object(root, v)
         | 
| 41 | 
            +
                    _update_child_object(v, obj)
         | 
| 42 | 
            +
                    self.instance_variable_set("@#{name}", obj)
         | 
| 43 | 
            +
                  elsif v.is_a?(OpenAPIParser::Expandable)
         | 
| 44 | 
            +
                    v.expand_reference(root)
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
              def expand_list_objects(root, attribute_names)
         | 
| 50 | 
            +
                return unless attribute_names
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                attribute_names.each do |name|
         | 
| 53 | 
            +
                  l = send(name)
         | 
| 54 | 
            +
                  next if l.nil?
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                  l.each_with_index do |v, idx|
         | 
| 57 | 
            +
                    if v.is_a?(OpenAPIParser::Schemas::Reference)
         | 
| 58 | 
            +
                      obj = referenced_object(root, v)
         | 
| 59 | 
            +
                      _update_child_object(v, obj)
         | 
| 60 | 
            +
                      l[idx] = obj
         | 
| 61 | 
            +
                    elsif v.is_a?(OpenAPIParser::Expandable)
         | 
| 62 | 
            +
                      v.expand_reference(root)
         | 
| 63 | 
            +
                    end
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
              end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
             | 
| 69 | 
            +
              # @param [OpenAPIParser::Schemas::OpenAPI] root
         | 
| 70 | 
            +
              # @param [OpenAPIParser::Schemas::Reference] reference
         | 
| 71 | 
            +
              def referenced_object(root, reference)
         | 
| 72 | 
            +
                obj = root.find_object(reference.ref)
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                obj.is_a?(OpenAPIParser::Schemas::Reference) ? referenced_object(root, obj) : obj
         | 
| 75 | 
            +
              end
         | 
| 76 | 
            +
            end
         | 
| @@ -10,7 +10,12 @@ module OpenAPIParser::Findable | |
| 10 10 | 
             
                  return obj
         | 
| 11 11 | 
             
                end
         | 
| 12 12 |  | 
| 13 | 
            -
                 | 
| 13 | 
            +
                if (child = _openapi_all_child_objects[reference])
         | 
| 14 | 
            +
                  @find_object_cache[reference] = child
         | 
| 15 | 
            +
                  return child
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                _openapi_all_child_objects.values.each do |c|
         | 
| 14 19 | 
             
                  if (obj = c.find_object(reference))
         | 
| 15 20 | 
             
                    @find_object_cache[reference] = obj
         | 
| 16 21 | 
             
                    return obj
         | 
| @@ -19,4 +24,10 @@ module OpenAPIParser::Findable | |
| 19 24 |  | 
| 20 25 | 
             
                nil
         | 
| 21 26 | 
             
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              def purge_object_cache
         | 
| 29 | 
            +
                @find_object_cache = {}
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                _openapi_all_child_objects.values.each(&:purge_object_cache)
         | 
| 32 | 
            +
              end
         | 
| 22 33 | 
             
            end
         | 
| @@ -57,16 +57,22 @@ module OpenAPIParser::Parseable | |
| 57 57 | 
             
                end
         | 
| 58 58 | 
             
              end
         | 
| 59 59 |  | 
| 60 | 
            +
              def child_from_reference(reference)
         | 
| 61 | 
            +
                _openapi_all_child_objects[reference]
         | 
| 62 | 
            +
              end
         | 
| 60 63 |  | 
| 61 64 | 
             
              def _openapi_all_child_objects
         | 
| 62 | 
            -
                @_openapi_all_child_objects ||=  | 
| 65 | 
            +
                @_openapi_all_child_objects ||= {}
         | 
| 63 66 | 
             
              end
         | 
| 64 67 |  | 
| 65 68 | 
             
              def _add_child_object(object)
         | 
| 66 69 | 
             
                return unless object.is_a?(OpenAPIParser::Parseable)
         | 
| 67 | 
            -
                _openapi_all_child_objects  | 
| 70 | 
            +
                _openapi_all_child_objects[object.object_reference] = object
         | 
| 68 71 | 
             
              end
         | 
| 69 72 |  | 
| 73 | 
            +
              def _update_child_object(old, new)
         | 
| 74 | 
            +
                _openapi_all_child_objects[old.object_reference] = new
         | 
| 75 | 
            +
              end
         | 
| 70 76 |  | 
| 71 77 | 
             
              def load_data
         | 
| 72 78 | 
             
                create_attr_values(self.class._openapi_attr_values)
         | 
| @@ -0,0 +1,24 @@ | |
| 1 | 
            +
            class OpenAPIParser::Config
         | 
| 2 | 
            +
              def initialize(config)
         | 
| 3 | 
            +
                @config = config
         | 
| 4 | 
            +
              end
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              def datetime_coerce_class
         | 
| 7 | 
            +
                @config[:datetime_coerce_class]
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              def coerce_value
         | 
| 11 | 
            +
                @config[:coerce_value]
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              def expand_reference
         | 
| 15 | 
            +
                @config.fetch(:expand_reference, true)
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              def request_validator_options
         | 
| 19 | 
            +
                @request_options ||= OpenAPIParser::SchemaValidator::Options.new(coerce_value: coerce_value, datetime_coerce_class: datetime_coerce_class)
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              alias_method :request_body_options, :request_validator_options
         | 
| 23 | 
            +
              alias_method :path_params_options, :request_validator_options
         | 
| 24 | 
            +
            end
         | 
| @@ -0,0 +1,58 @@ | |
| 1 | 
            +
            module OpenAPIParser
         | 
| 2 | 
            +
              class OpenAPIError < StandardError
         | 
| 3 | 
            +
                def initialize(reference)
         | 
| 4 | 
            +
                  @reference = reference
         | 
| 5 | 
            +
                end
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              class ValidateError < OpenAPIError
         | 
| 9 | 
            +
                def initialize(data, type, reference)
         | 
| 10 | 
            +
                  super(reference)
         | 
| 11 | 
            +
                  @data = data
         | 
| 12 | 
            +
                  @type = type
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def message
         | 
| 16 | 
            +
                  "#{@data} class is #{@data.class} but it's not valid #{@type} in #{@reference}"
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              class NotNullError < OpenAPIError
         | 
| 21 | 
            +
                def message
         | 
| 22 | 
            +
                  "#{@reference} don't allow null"
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              class NotExistRequiredKey < OpenAPIError
         | 
| 27 | 
            +
                def initialize(keys, reference)
         | 
| 28 | 
            +
                  super(reference)
         | 
| 29 | 
            +
                  @keys = keys
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def message
         | 
| 33 | 
            +
                  "required parameters #{@keys.join(",")} not exist in #{@reference}"
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              class NotAnyOf < OpenAPIError
         | 
| 38 | 
            +
                def initialize(value, reference)
         | 
| 39 | 
            +
                  super(reference)
         | 
| 40 | 
            +
                  @value = value
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                def message
         | 
| 44 | 
            +
                  "#{@value} isn't any of in #{@reference}"
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
              class NotEnumInclude < OpenAPIError
         | 
| 49 | 
            +
                def initialize(value, reference)
         | 
| 50 | 
            +
                  super(reference)
         | 
| 51 | 
            +
                  @value = value
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                def message
         | 
| 55 | 
            +
                  "#{@value} isn't include enum in #{@reference}"
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
            end
         | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            class OpenAPIParser::ParameterValidator
         | 
| 2 | 
            +
              class << self
         | 
| 3 | 
            +
                # @param [Hash{String => Parameter}] parameters_hash
         | 
| 4 | 
            +
                # @param [Hash] params
         | 
| 5 | 
            +
                # @param [String] object_reference
         | 
| 6 | 
            +
                # @param [OpenAPIParser::SchemaValidator::Options] options
         | 
| 7 | 
            +
                def validate_parameter(parameters_hash, params, object_reference, options)
         | 
| 8 | 
            +
                  no_exist_required_key = []
         | 
| 9 | 
            +
                  parameters_hash.each do |k, v|
         | 
| 10 | 
            +
                    if (data = params[k])
         | 
| 11 | 
            +
                      coerced = v.validate_params(data, options)
         | 
| 12 | 
            +
                      params[k] = coerced if options.coerce_value
         | 
| 13 | 
            +
                    elsif v.required
         | 
| 14 | 
            +
                      no_exist_required_key << k
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  raise OpenAPIParser::NotExistRequiredKey.new(no_exist_required_key, object_reference) unless no_exist_required_key.empty?
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  params
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
            end
         | 
| @@ -9,11 +9,11 @@ class OpenAPIParser::PathItemFinder | |
| 9 9 |  | 
| 10 10 | 
             
              # @param [String, Symbol] http_method like (get, post .... allow symbol)
         | 
| 11 11 | 
             
              # @param [String] request_path
         | 
| 12 | 
            -
              #  | 
| 12 | 
            +
              # return operation_object, original_path, path_params
         | 
| 13 13 | 
             
              def operation_object(http_method, request_path)
         | 
| 14 14 | 
             
                if (path_item_object = @paths.path[request_path])
         | 
| 15 15 | 
             
                  if (op = path_item_object.operation(http_method))
         | 
| 16 | 
            -
                    return op, {} # find no path_params path
         | 
| 16 | 
            +
                    return op, request_path, {} # find no path_params path
         | 
| 17 17 | 
             
                  end
         | 
| 18 18 | 
             
                end
         | 
| 19 19 |  | 
| @@ -83,11 +83,11 @@ class OpenAPIParser::PathItemFinder | |
| 83 83 |  | 
| 84 84 | 
             
              def parse_request_path(http_method, request_path)
         | 
| 85 85 | 
             
                original_path, path_params = @root.find_full_path(request_path.split("/"))
         | 
| 86 | 
            -
                return nil,  | 
| 86 | 
            +
                return nil, nil, {} unless original_path # # can't find
         | 
| 87 87 |  | 
| 88 88 | 
             
                path_item_object = @paths.path[original_path]
         | 
| 89 89 | 
             
                obj = path_item_object.operation(http_method.to_s)
         | 
| 90 90 |  | 
| 91 | 
            -
                [obj, path_params]
         | 
| 91 | 
            +
                [obj, original_path, path_params]
         | 
| 92 92 | 
             
              end
         | 
| 93 93 | 
             
            end
         | 
| @@ -2,29 +2,56 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            class OpenAPIParser::RequestOperation
         | 
| 4 4 | 
             
              class << self
         | 
| 5 | 
            +
                # @param [OpenAPIParser::Config] config
         | 
| 5 6 | 
             
                # @param [OpenAPIParser::PathItemFinder] path_item_finder
         | 
| 6 | 
            -
                 | 
| 7 | 
            -
             | 
| 7 | 
            +
                # @return [OpenAPIParser::RequestOperation, nil]
         | 
| 8 | 
            +
                def create(http_method, request_path, path_item_finder, config)
         | 
| 9 | 
            +
                  operation, original_path, path_params = path_item_finder.operation_object(http_method, request_path)
         | 
| 8 10 |  | 
| 9 | 
            -
                  return nil unless  | 
| 11 | 
            +
                  return nil unless operation
         | 
| 10 12 |  | 
| 11 | 
            -
                  self.new( | 
| 13 | 
            +
                  self.new(http_method, original_path, operation, path_params, config)
         | 
| 12 14 | 
             
                end
         | 
| 13 15 | 
             
              end
         | 
| 14 16 |  | 
| 15 17 | 
             
              # @!attribute [r] operation_object
         | 
| 16 | 
            -
              #   @return [OpenAPIParser::Schemas::Operation | 
| 18 | 
            +
              #   @return [OpenAPIParser::Schemas::Operation]
         | 
| 17 19 | 
             
              # @!attribute [r] path_params
         | 
| 18 20 | 
             
              #   @return [Hash{String => String}]
         | 
| 19 | 
            -
               | 
| 21 | 
            +
              # @!attribute [r] config
         | 
| 22 | 
            +
              #   #   @return [OpenAPIParser::Config]
         | 
| 23 | 
            +
              # @!attribute [r] http_method
         | 
| 24 | 
            +
              #   @return [String]
         | 
| 25 | 
            +
              # @!attribute [r] original_path
         | 
| 26 | 
            +
              #   @return [String]
         | 
| 27 | 
            +
              attr_reader :operation_object, :path_params, :config, :http_method, :original_path
         | 
| 20 28 |  | 
| 21 | 
            -
               | 
| 29 | 
            +
              # @param [OpenAPIParser::Config] config
         | 
| 30 | 
            +
              def initialize(http_method, original_path, operation_object, path_params, config)
         | 
| 31 | 
            +
                @http_method = http_method.to_s
         | 
| 32 | 
            +
                @original_path = original_path
         | 
| 22 33 | 
             
                @operation_object = operation_object
         | 
| 23 34 | 
             
                @path_params = path_params || {}
         | 
| 35 | 
            +
                @config = config
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              def validate_path_params(options = nil)
         | 
| 39 | 
            +
                options = config.path_params_options unless options
         | 
| 40 | 
            +
                operation_object&.validate_path_params(path_params, options)
         | 
| 24 41 | 
             
              end
         | 
| 25 42 |  | 
| 26 43 | 
             
              # support application/json only :(
         | 
| 27 | 
            -
              def validate_request_body(content_type, params)
         | 
| 28 | 
            -
                 | 
| 44 | 
            +
              def validate_request_body(content_type, params, options = nil)
         | 
| 45 | 
            +
                options = config.request_body_options unless options
         | 
| 46 | 
            +
                operation_object&.validate_request_body(content_type, params, options)
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
              def validate_response_body(status_code, content_type, data)
         | 
| 50 | 
            +
                operation_object&.validate_response_body(status_code, content_type, data)
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
              def validate_request_parameter(params, options = nil)
         | 
| 54 | 
            +
                options = config.request_validator_options unless options
         | 
| 55 | 
            +
                operation_object&.validate_request_parameter(params, options)
         | 
| 29 56 | 
             
              end
         | 
| 30 57 | 
             
            end
         | 
| @@ -1,172 +1,109 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
             | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
              end
         | 
| 13 | 
            -
             | 
| 14 | 
            -
              class NotNullError < StandardError
         | 
| 15 | 
            -
                def initialize(reference)
         | 
| 16 | 
            -
                  @reference = reference
         | 
| 17 | 
            -
                end
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                def message
         | 
| 20 | 
            -
                  "#{@reference} don't allow null"
         | 
| 21 | 
            -
                end
         | 
| 22 | 
            -
              end
         | 
| 1 | 
            +
            require_relative 'schema_validators/options'
         | 
| 2 | 
            +
            require_relative 'schema_validators/enumable'
         | 
| 3 | 
            +
            require_relative 'schema_validators/base'
         | 
| 4 | 
            +
            require_relative 'schema_validators/string_validator'
         | 
| 5 | 
            +
            require_relative 'schema_validators/integer_validator'
         | 
| 6 | 
            +
            require_relative 'schema_validators/float_validator'
         | 
| 7 | 
            +
            require_relative 'schema_validators/boolean_validator'
         | 
| 8 | 
            +
            require_relative 'schema_validators/object_validator'
         | 
| 9 | 
            +
            require_relative 'schema_validators/array_validator'
         | 
| 10 | 
            +
            require_relative 'schema_validators/any_of_validator'
         | 
| 11 | 
            +
            require_relative 'schema_validators/nil_validator'
         | 
| 23 12 |  | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
                  @keys = keys
         | 
| 27 | 
            -
                  @reference = reference
         | 
| 28 | 
            -
                end
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                def message
         | 
| 31 | 
            -
                  "required parameters #{@keys.join(",")} not exist in #{@reference}"
         | 
| 32 | 
            -
                end
         | 
| 33 | 
            -
              end
         | 
| 34 | 
            -
             | 
| 35 | 
            -
              class NotAnyOf < StandardError
         | 
| 36 | 
            -
                def initialize(value, reference)
         | 
| 37 | 
            -
                  @value = value
         | 
| 38 | 
            -
                  @reference = reference
         | 
| 39 | 
            -
                end
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                def message
         | 
| 42 | 
            -
                  "#{@value} isn't any of in #{@reference}"
         | 
| 43 | 
            -
                end
         | 
| 44 | 
            -
              end
         | 
| 45 | 
            -
             | 
| 46 | 
            -
              class NotEnumInclude < StandardError
         | 
| 47 | 
            -
                def initialize(value, reference)
         | 
| 48 | 
            -
                  @value = value
         | 
| 49 | 
            -
                  @reference = reference
         | 
| 50 | 
            -
                end
         | 
| 13 | 
            +
            class OpenAPIParser::SchemaValidator
         | 
| 14 | 
            +
              class ValidatorOption
         | 
| 51 15 |  | 
| 52 | 
            -
                def message
         | 
| 53 | 
            -
                  "#{@value} isn't include enum in #{@reference}"
         | 
| 54 | 
            -
                end
         | 
| 55 16 | 
             
              end
         | 
| 56 17 |  | 
| 57 18 | 
             
              class << self
         | 
| 58 19 | 
             
                # @param [Hash] value
         | 
| 59 20 | 
             
                # @param [OpenAPIParser::Schemas::Schema]
         | 
| 60 | 
            -
                 | 
| 61 | 
            -
             | 
| 21 | 
            +
                # @param [OpenAPIParser::SchemaValidator::Options] options
         | 
| 22 | 
            +
                # @return [Object] coerced or original params
         | 
| 23 | 
            +
                def validate(value, schema, options)
         | 
| 24 | 
            +
                  new(value, schema, options).validate_data
         | 
| 62 25 | 
             
                end
         | 
| 63 26 | 
             
              end
         | 
| 64 27 |  | 
| 65 28 | 
             
              # @param [Hash] value
         | 
| 66 29 | 
             
              # @param [OpenAPIParser::Schemas::Schema] schema
         | 
| 67 | 
            -
               | 
| 30 | 
            +
              # @param [OpenAPIParser::SchemaValidator::Options] options
         | 
| 31 | 
            +
              def initialize(value, schema, options)
         | 
| 68 32 | 
             
                @value = value
         | 
| 69 33 | 
             
                @schema = schema
         | 
| 34 | 
            +
                @coerce_value = options.coerce_value
         | 
| 35 | 
            +
                @datetime_coerce_class = options.datetime_coerce_class
         | 
| 70 36 | 
             
              end
         | 
| 71 37 |  | 
| 38 | 
            +
              # @return [Object] coerced or original params
         | 
| 72 39 | 
             
              def validate_data
         | 
| 73 | 
            -
                err = validate_schema(@value, @schema)
         | 
| 40 | 
            +
                coerced, err = validate_schema(@value, @schema)
         | 
| 74 41 | 
             
                raise err if err
         | 
| 75 | 
            -
                 | 
| 42 | 
            +
                coerced
         | 
| 76 43 | 
             
              end
         | 
| 77 44 |  | 
| 78 | 
            -
               | 
| 79 | 
            -
             | 
| 80 | 
            -
              # @param [Object] value
         | 
| 81 | 
            -
              # @param [OpenAPIParser::Schemas::Schema] schema
         | 
| 82 | 
            -
              def validate_schema(value, schema)
         | 
| 83 | 
            -
                return unless schema
         | 
| 84 | 
            -
                return validate_any_of(value, schema) if schema.any_of
         | 
| 85 | 
            -
             | 
| 86 | 
            -
                if value.nil?
         | 
| 87 | 
            -
                  return if schema.nullable
         | 
| 88 | 
            -
                  return NotNullError.new(schema.object_reference)
         | 
| 89 | 
            -
                end
         | 
| 90 | 
            -
             | 
| 91 | 
            -
                case schema.type
         | 
| 92 | 
            -
                when "string"
         | 
| 93 | 
            -
                  return validate_string(value, schema) if value.is_a?(String)
         | 
| 94 | 
            -
                when "integer"
         | 
| 95 | 
            -
                  return validate_integer(value, schema) if value.is_a?(Integer)
         | 
| 96 | 
            -
                when "boolean"
         | 
| 97 | 
            -
                  return if value.is_a?(TrueClass)
         | 
| 98 | 
            -
                  return if value.is_a?(FalseClass)
         | 
| 99 | 
            -
                when "number"
         | 
| 100 | 
            -
                  return validate_integer(value, schema) if value.is_a?(Integer)
         | 
| 101 | 
            -
                  return validate_number(value, schema) if value.is_a?(Numeric)
         | 
| 102 | 
            -
                when "object"
         | 
| 103 | 
            -
                  return validate_object(value, schema) if value.is_a?(Hash)
         | 
| 104 | 
            -
                when "array"
         | 
| 105 | 
            -
                  return validate_array(value, schema) if value.is_a?(Array)
         | 
| 106 | 
            -
                else
         | 
| 107 | 
            -
                  # TODO: unknown type support
         | 
| 108 | 
            -
                end
         | 
| 109 | 
            -
             | 
| 110 | 
            -
                ValidateError.new(value, schema.type, schema.object_reference)
         | 
| 111 | 
            -
              end
         | 
| 112 | 
            -
             | 
| 113 | 
            -
              # @param [Object] value
         | 
| 114 | 
            -
              # @param [OpenAPIParser::Schemas::Schema] schema
         | 
| 115 | 
            -
              def validate_any_of(value, schema)
         | 
| 116 | 
            -
                # in all schema return error (=true) not any of data
         | 
| 117 | 
            -
                schema.any_of.all? { |s| validate_schema(value, s) } ? NotAnyOf.new(value, schema.object_reference) : nil
         | 
| 45 | 
            +
              def validate_error(value, schema)
         | 
| 46 | 
            +
                [nil, OpenAPIParser::ValidateError.new(value, schema.type, schema.object_reference)]
         | 
| 118 47 | 
             
              end
         | 
| 119 48 |  | 
| 120 49 | 
             
              def validate_string(value, schema)
         | 
| 121 | 
            -
                 | 
| 50 | 
            +
                (@string_validator ||= OpenAPIParser::SchemaValidator::StringValidator.new(self, @coerce_value, @datetime_coerce_class)).coerce_and_validate(value, schema)
         | 
| 122 51 | 
             
              end
         | 
| 123 52 |  | 
| 124 53 | 
             
              def validate_integer(value, schema)
         | 
| 125 | 
            -
                 | 
| 54 | 
            +
                (@integer_validator ||= OpenAPIParser::SchemaValidator::IntegerValidator.new(self, @coerce_value)).coerce_and_validate(value, schema)
         | 
| 126 55 | 
             
              end
         | 
| 127 56 |  | 
| 128 | 
            -
              def  | 
| 129 | 
            -
                 | 
| 57 | 
            +
              def validate_float(value, schema)
         | 
| 58 | 
            +
                (@float_validator ||= OpenAPIParser::SchemaValidator::FloatValidator.new(self, @coerce_value)).coerce_and_validate(value, schema)
         | 
| 130 59 | 
             
              end
         | 
| 131 60 |  | 
| 132 | 
            -
               | 
| 133 | 
            -
             | 
| 134 | 
            -
              def check_enum_include(value, schema)
         | 
| 135 | 
            -
                return unless schema.enum
         | 
| 136 | 
            -
                return if schema.enum.include?(value)
         | 
| 137 | 
            -
             | 
| 138 | 
            -
                NotEnumInclude.new(value, schema.object_reference)
         | 
| 61 | 
            +
              def validate_boolean(value, schema)
         | 
| 62 | 
            +
                (@boolean_validator ||= OpenAPIParser::SchemaValidator::BooleanValidator.new(self, @coerce_value)).coerce_and_validate(value, schema)
         | 
| 139 63 | 
             
              end
         | 
| 140 64 |  | 
| 141 | 
            -
              # @param [Hash] value
         | 
| 142 | 
            -
              # @param [OpenAPIParser::Schemas::Schema] schema
         | 
| 143 65 | 
             
              def validate_object(value, schema)
         | 
| 144 | 
            -
                 | 
| 145 | 
            -
             | 
| 66 | 
            +
                (@object_validator ||= OpenAPIParser::SchemaValidator::ObjectValidator.new(self, @coerce_value)).coerce_and_validate(value, schema)
         | 
| 67 | 
            +
              end
         | 
| 146 68 |  | 
| 147 | 
            -
             | 
| 148 | 
            -
             | 
| 149 | 
            -
             | 
| 150 | 
            -
                  return err if err
         | 
| 69 | 
            +
              def validate_array(value, schema)
         | 
| 70 | 
            +
                (@array_validator ||= OpenAPIParser::SchemaValidator::ArrayValidator.new(self, @coerce_value)).coerce_and_validate(value, schema)
         | 
| 71 | 
            +
              end
         | 
| 151 72 |  | 
| 152 | 
            -
             | 
| 153 | 
            -
                 | 
| 73 | 
            +
              def validate_any_of(value, schema)
         | 
| 74 | 
            +
                (@any_of_validator ||= OpenAPIParser::SchemaValidator::AnyOfValidator.new(self, @coerce_value)).coerce_and_validate(value, schema)
         | 
| 75 | 
            +
              end
         | 
| 154 76 |  | 
| 155 | 
            -
             | 
| 156 | 
            -
                 | 
| 77 | 
            +
              def validate_nil(value, schema)
         | 
| 78 | 
            +
                (@nil_validator ||= OpenAPIParser::SchemaValidator::NilValidator.new(self, @coerce_value)).coerce_and_validate(value, schema)
         | 
| 157 79 | 
             
              end
         | 
| 158 80 |  | 
| 159 | 
            -
              # @param [ | 
| 81 | 
            +
              # @param [Object] value
         | 
| 160 82 | 
             
              # @param [OpenAPIParser::Schemas::Schema] schema
         | 
| 161 | 
            -
              def  | 
| 162 | 
            -
                 | 
| 163 | 
            -
             | 
| 83 | 
            +
              def validate_schema(value, schema)
         | 
| 84 | 
            +
                return [value, nil] unless schema # no schema
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                return validate_any_of(value, schema) if schema.any_of
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                return validate_nil(value, schema) if value.nil?
         | 
| 164 89 |  | 
| 165 | 
            -
                 | 
| 166 | 
            -
             | 
| 167 | 
            -
                  return  | 
| 90 | 
            +
                case schema.type
         | 
| 91 | 
            +
                when "string"
         | 
| 92 | 
            +
                  return validate_string(value, schema)
         | 
| 93 | 
            +
                when "integer"
         | 
| 94 | 
            +
                  return validate_integer(value, schema)
         | 
| 95 | 
            +
                when "boolean"
         | 
| 96 | 
            +
                  return validate_boolean(value, schema)
         | 
| 97 | 
            +
                when "number"
         | 
| 98 | 
            +
                  return validate_float(value, schema)
         | 
| 99 | 
            +
                when "object"
         | 
| 100 | 
            +
                  return validate_object(value, schema)
         | 
| 101 | 
            +
                when "array"
         | 
| 102 | 
            +
                  return validate_array(value, schema)
         | 
| 103 | 
            +
                else
         | 
| 104 | 
            +
                  # TODO: unknown type support
         | 
| 168 105 | 
             
                end
         | 
| 169 106 |  | 
| 170 | 
            -
                 | 
| 107 | 
            +
                validate_error(value, schema)
         | 
| 171 108 | 
             
              end
         | 
| 172 109 | 
             
            end
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            class OpenAPIParser::SchemaValidator
         | 
| 2 | 
            +
              class AnyOfValidator < Base
         | 
| 3 | 
            +
                # @param [Object] value
         | 
| 4 | 
            +
                # @param [OpenAPIParser::Schemas::Schema] schema
         | 
| 5 | 
            +
                def coerce_and_validate(value, schema)
         | 
| 6 | 
            +
                  # in all schema return error (=true) not any of data
         | 
| 7 | 
            +
                  schema.any_of.each do |s|
         | 
| 8 | 
            +
                    coerced, err = validator.validate_schema(value, s)
         | 
| 9 | 
            +
                    return [coerced, nil] if err.nil?
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
                  [nil, OpenAPIParser::NotAnyOf.new(value, schema.object_reference)]
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
            end
         | 
| @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            class OpenAPIParser::SchemaValidator
         | 
| 2 | 
            +
              class ArrayValidator < Base
         | 
| 3 | 
            +
             | 
| 4 | 
            +
                # @param [Array] value
         | 
| 5 | 
            +
                # @param [OpenAPIParser::Schemas::Schema] schema
         | 
| 6 | 
            +
                def coerce_and_validate(value, schema)
         | 
| 7 | 
            +
                  return validator.validate_error(value, schema) unless value.is_a?(Array)
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  # array type have an schema in items property
         | 
| 10 | 
            +
                  items_schema = schema.items
         | 
| 11 | 
            +
             | 
| 12 | 
            +
             | 
| 13 | 
            +
                  coerced_values = value.map do |v|
         | 
| 14 | 
            +
                    coerced, err = validator.validate_schema(v, items_schema)
         | 
| 15 | 
            +
                    return [nil, err] if err
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                    coerced
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  value.each_index { |idx| value[idx] = coerced_values[idx] } if @coerce_value
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  [value, nil]
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
            end
         | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            class OpenAPIParser::SchemaValidator
         | 
| 2 | 
            +
              class Base
         | 
| 3 | 
            +
                def initialize(validator, coerce_value)
         | 
| 4 | 
            +
                  @validator = validator
         | 
| 5 | 
            +
                  @coerce_value = coerce_value
         | 
| 6 | 
            +
                end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                attr_reader :validator
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                # @!attribute [r] validator
         | 
| 11 | 
            +
                #   @return [OpenAPIParser::SchemaValidator]
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                # return  [coerced_value, error]
         | 
| 14 | 
            +
                def coerce_and_validate(_value, _schema)
         | 
| 15 | 
            +
                  raise 'need implement'
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
            end
         | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            class OpenAPIParser::SchemaValidator
         | 
| 2 | 
            +
              class BooleanValidator < Base
         | 
| 3 | 
            +
                def coerce_and_validate(value, schema)
         | 
| 4 | 
            +
                  value = coerce(value) if @coerce_value
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                  return validator.validate_error(value, schema) unless value.is_a?(TrueClass) || value.is_a?(FalseClass)
         | 
| 7 | 
            +
                  [value, nil]
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                private
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def coerce(value)
         | 
| 13 | 
            +
                  if value == "true" || value == "1"
         | 
| 14 | 
            +
                    return true
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                  if value == "false" || value == "0"
         | 
| 17 | 
            +
                    return false
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                  value
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
            end
         | 
| @@ -0,0 +1,10 @@ | |
| 1 | 
            +
            class OpenAPIParser::SchemaValidator
         | 
| 2 | 
            +
              module Enumable
         | 
| 3 | 
            +
                def check_enum_include(value, schema)
         | 
| 4 | 
            +
                  return [value, nil] unless schema.enum
         | 
| 5 | 
            +
                  return [value, nil] if schema.enum.include?(value)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  [nil, OpenAPIParser::NotEnumInclude.new(value, schema.object_reference)]
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
            end
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            class OpenAPIParser::SchemaValidator
         | 
| 2 | 
            +
              class FloatValidator < Base
         | 
| 3 | 
            +
                include ::OpenAPIParser::SchemaValidator::Enumable
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def coerce_and_validate(value, schema)
         | 
| 6 | 
            +
                  value = coerce(value) if @coerce_value
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  return validator.validate_integer(value, schema) if value.is_a?(Integer)
         | 
| 9 | 
            +
                  coercer_and_validate_numeric(value, schema)
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                private
         | 
| 13 | 
            +
             | 
| 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
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                private
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def coerce(value)
         | 
| 22 | 
            +
                  begin
         | 
| 23 | 
            +
                    return Float(value)
         | 
| 24 | 
            +
                  rescue ArgumentError => e
         | 
| 25 | 
            +
                    raise e unless e.message =~ /invalid value for Float/
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
            end
         | 
| @@ -0,0 +1,26 @@ | |
| 1 | 
            +
            class OpenAPIParser::SchemaValidator
         | 
| 2 | 
            +
              class IntegerValidator < Base
         | 
| 3 | 
            +
                include ::OpenAPIParser::SchemaValidator::Enumable
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def coerce_and_validate(value, schema)
         | 
| 6 | 
            +
                  value = coerce(value) if @coerce_value
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  return validator.validate_error(value, schema) unless value.is_a?(Integer)
         | 
| 9 | 
            +
                  check_enum_include(value, schema)
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                private
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                def coerce(value)
         | 
| 15 | 
            +
                  return value if value.is_a?(Integer)
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  begin
         | 
| 18 | 
            +
                    return Integer(value)
         | 
| 19 | 
            +
                  rescue ArgumentError => e
         | 
| 20 | 
            +
                    raise e unless e.message =~ /invalid value for Integer/
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  value
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
            end
         | 
| @@ -0,0 +1,10 @@ | |
| 1 | 
            +
            class OpenAPIParser::SchemaValidator
         | 
| 2 | 
            +
              class NilValidator < Base
         | 
| 3 | 
            +
                # @param [Object] value
         | 
| 4 | 
            +
                # @param [OpenAPIParser::Schemas::Schema] schema
         | 
| 5 | 
            +
                def coerce_and_validate(value, schema)
         | 
| 6 | 
            +
                  return [value, nil] if schema.nullable
         | 
| 7 | 
            +
                  [nil, OpenAPIParser::NotNullError.new(schema.object_reference)]
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
            end
         | 
| @@ -0,0 +1,28 @@ | |
| 1 | 
            +
            class OpenAPIParser::SchemaValidator
         | 
| 2 | 
            +
              class ObjectValidator < Base
         | 
| 3 | 
            +
             | 
| 4 | 
            +
                # @param [Hash] value
         | 
| 5 | 
            +
                # @param [OpenAPIParser::Schemas::Schema] schema
         | 
| 6 | 
            +
                def coerce_and_validate(value, schema)
         | 
| 7 | 
            +
                  return validator.validate_error(value, schema) unless value.is_a?(Hash)
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  return [value, nil] unless schema.properties
         | 
| 10 | 
            +
                  required_set = schema.required ? schema.required.to_set : Set.new
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  coerced_values = value.map do |name, v|
         | 
| 13 | 
            +
                    s = schema.properties[name]
         | 
| 14 | 
            +
                    coerced, err = validator.validate_schema(v, s)
         | 
| 15 | 
            +
                    return [nil, err] if err
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                    required_set.delete(name)
         | 
| 18 | 
            +
                    [name, coerced]
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  return [nil, OpenAPIParser::NotExistRequiredKey.new(required_set.to_a, schema.object_reference)] unless required_set.empty?
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  value = value.merge(coerced_values.to_h) if @coerce_value
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  [value, nil]
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
            end
         | 
| @@ -0,0 +1,10 @@ | |
| 1 | 
            +
            class OpenAPIParser::SchemaValidator
         | 
| 2 | 
            +
              class Options
         | 
| 3 | 
            +
                attr_reader :coerce_value, :datetime_coerce_class
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def initialize(coerce_value: nil, datetime_coerce_class: nil)
         | 
| 6 | 
            +
                  @coerce_value = coerce_value
         | 
| 7 | 
            +
                  @datetime_coerce_class = datetime_coerce_class
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
            end
         | 
| @@ -0,0 +1,38 @@ | |
| 1 | 
            +
            class OpenAPIParser::SchemaValidator
         | 
| 2 | 
            +
              class StringValidator < Base
         | 
| 3 | 
            +
                include ::OpenAPIParser::SchemaValidator::Enumable
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def initialize(validator, coerce_value, datetime_coerce_class)
         | 
| 6 | 
            +
                  super(validator, coerce_value)
         | 
| 7 | 
            +
                  @datetime_coerce_class = datetime_coerce_class
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def coerce_and_validate(value, schema)
         | 
| 11 | 
            +
                  return validator.validate_error(value, schema) unless value.is_a?(String)
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  value, err = check_enum_include(value, schema)
         | 
| 14 | 
            +
                  return [nil, err] if err
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  value = coerce_date_time(value, schema) unless @datetime_coerce_class.nil?
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  [value, nil]
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                private
         | 
| 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/
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  value
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
            end
         | 
| @@ -9,8 +9,8 @@ module OpenAPIParser::Schemas | |
| 9 9 | 
             
                openapi_attr_object :schema, Schema, reference: true
         | 
| 10 10 |  | 
| 11 11 | 
             
                # @param [Hash] params
         | 
| 12 | 
            -
                def validate_parameter(params)
         | 
| 13 | 
            -
                  OpenAPIParser::SchemaValidator.validate(params, schema)
         | 
| 12 | 
            +
                def validate_parameter(params, options)
         | 
| 13 | 
            +
                  OpenAPIParser::SchemaValidator.validate(params, schema, options)
         | 
| 14 14 | 
             
                end
         | 
| 15 15 | 
             
              end
         | 
| 16 16 | 
             
            end
         | 
| @@ -5,10 +5,11 @@ | |
| 5 5 |  | 
| 6 6 | 
             
            module OpenAPIParser::Schemas
         | 
| 7 7 | 
             
              class OpenAPI < Base
         | 
| 8 | 
            -
                def initialize(raw_schema)
         | 
| 8 | 
            +
                def initialize(raw_schema, config)
         | 
| 9 9 | 
             
                  super('#', nil, self, raw_schema)
         | 
| 10 10 | 
             
                  @find_object_cache = {}
         | 
| 11 11 | 
             
                  @path_item_finder = OpenAPIParser::PathItemFinder.new(paths)
         | 
| 12 | 
            +
                  @config = config
         | 
| 12 13 | 
             
                end
         | 
| 13 14 |  | 
| 14 15 | 
             
                # @!attribute [r] openapi
         | 
| @@ -23,9 +24,9 @@ module OpenAPIParser::Schemas | |
| 23 24 | 
             
                #   @return [Components, nil]
         | 
| 24 25 | 
             
                openapi_attr_object :components, Components, reference: false
         | 
| 25 26 |  | 
| 26 | 
            -
                # @return [OpenAPIParser::RequestOperation]
         | 
| 27 | 
            +
                # @return [OpenAPIParser::RequestOperation, nil]
         | 
| 27 28 | 
             
                def request_operation(http_method, request_path)
         | 
| 28 | 
            -
                  OpenAPIParser::RequestOperation.create(http_method, request_path, @path_item_finder)
         | 
| 29 | 
            +
                  OpenAPIParser::RequestOperation.create(http_method, request_path, @path_item_finder, @config)
         | 
| 29 30 | 
             
                end
         | 
| 30 31 | 
             
              end
         | 
| 31 32 | 
             
            end
         | 
| @@ -17,8 +17,37 @@ module OpenAPIParser::Schemas | |
| 17 17 |  | 
| 18 18 | 
             
                openapi_attr_object :responses, Responses, reference: false
         | 
| 19 19 |  | 
| 20 | 
            -
                def validate_request_body(content_type, params)
         | 
| 21 | 
            -
                  request_body&.validate_request_body(content_type, params)
         | 
| 20 | 
            +
                def validate_request_body(content_type, params, options)
         | 
| 21 | 
            +
                  request_body&.validate_request_body(content_type, params, options)
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                def validate_response_body(status_code, content_type, data)
         | 
| 25 | 
            +
                  responses&.validate_response_body(status_code, content_type, data)
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                # @param [OpenAPIParser::SchemaValidator::Options] options
         | 
| 29 | 
            +
                def validate_request_parameter(params, options)
         | 
| 30 | 
            +
                  OpenAPIParser::ParameterValidator.validate_parameter(query_parameter_hash, params, object_reference, options)
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                def validate_path_params(path_params, options)
         | 
| 34 | 
            +
                  OpenAPIParser::ParameterValidator.validate_parameter(path_parameter_hash, path_params, object_reference, options)
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                private
         | 
| 38 | 
            +
             | 
| 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
         | 
| 22 51 | 
             
                end
         | 
| 23 52 | 
             
              end
         | 
| 24 53 | 
             
            end
         | 
| @@ -7,6 +7,22 @@ module OpenAPIParser::Schemas | |
| 7 7 | 
             
                openapi_attr_value :allow_empty_value, schema_key: :allowEmptyValue
         | 
| 8 8 | 
             
                openapi_attr_value :allow_reserved, schema_key: :allowReserved
         | 
| 9 9 |  | 
| 10 | 
            +
                # @!attribute [r] schema
         | 
| 11 | 
            +
                #   @return [Schema, Reference, nil]
         | 
| 10 12 | 
             
                openapi_attr_object :schema, Schema, reference: true
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                def in_query?
         | 
| 15 | 
            +
                  self.in == "query"
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                def in_path?
         | 
| 19 | 
            +
                  self.in == "path"
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                # @return [Object] coerced or original params
         | 
| 23 | 
            +
                # @param [OpenAPIParser::SchemaValidator::Options] options
         | 
| 24 | 
            +
                def validate_params(params, options)
         | 
| 25 | 
            +
                  ::OpenAPIParser::SchemaValidator.validate(params, schema, options)
         | 
| 26 | 
            +
                end
         | 
| 11 27 | 
             
              end
         | 
| 12 28 | 
             
            end
         | 
| @@ -8,13 +8,13 @@ module OpenAPIParser::Schemas | |
| 8 8 | 
             
                #   @return [Hash{String => MediaType}, nil]
         | 
| 9 9 | 
             
                openapi_attr_hash_object :content, MediaType, reference: false
         | 
| 10 10 |  | 
| 11 | 
            -
                def validate_request_body(_content_type, params)
         | 
| 11 | 
            +
                def validate_request_body(_content_type, params, options)
         | 
| 12 12 | 
             
                  # TODO: now support application/json only :(
         | 
| 13 13 |  | 
| 14 14 | 
             
                  media_type = content['application/json']
         | 
| 15 | 
            -
                  return  | 
| 15 | 
            +
                  return params unless media_type
         | 
| 16 16 |  | 
| 17 | 
            -
                  media_type.validate_parameter(params)
         | 
| 17 | 
            +
                  media_type.validate_parameter(params, options)
         | 
| 18 18 | 
             
                end
         | 
| 19 19 | 
             
              end
         | 
| 20 20 | 
             
            end
         | 
| @@ -8,5 +8,15 @@ module OpenAPIParser::Schemas | |
| 8 8 | 
             
                # @!attribute [r] content
         | 
| 9 9 | 
             
                #   @return [Hash{String => MediaType}, nil]
         | 
| 10 10 | 
             
                openapi_attr_hash_object :content, MediaType, reference: false
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def validate_parameter(content_type, params)
         | 
| 13 | 
            +
                  # TODO: support wildcard type like application/* (OpenAPI3 definition)
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  media_type = content[content_type]
         | 
| 16 | 
            +
                  return nil unless media_type
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  options = ::OpenAPIParser::SchemaValidator::Options.new # response validator not support any options
         | 
| 19 | 
            +
                  media_type.validate_parameter(params, options)
         | 
| 20 | 
            +
                end
         | 
| 11 21 | 
             
              end
         | 
| 12 22 | 
             
            end
         | 
| @@ -9,5 +9,16 @@ module OpenAPIParser::Schemas | |
| 9 9 | 
             
                # @!attribute [r] response
         | 
| 10 10 | 
             
                #   @return [Hash{String => Response, Reference}, nil]
         | 
| 11 11 | 
             
                openapi_attr_hash_body_objects 'response', Response, reject_keys: [:default], allow_reference: true, allow_data_type: false
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def validate_response_body(status_code, content_type, params)
         | 
| 14 | 
            +
                  # TODO: support wildcard status code like 2XX
         | 
| 15 | 
            +
                  return nil unless response
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  res = response[status_code.to_s]
         | 
| 18 | 
            +
                  return res.validate_parameter(content_type, params) if res
         | 
| 19 | 
            +
             | 
| 20 | 
            +
             | 
| 21 | 
            +
                  default&.validate_parameter(content_type, params)
         | 
| 22 | 
            +
                end
         | 
| 12 23 | 
             
              end
         | 
| 13 24 | 
             
            end
         | 
    
        data/openapi_parser.gemspec
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: openapi_parser
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.1. | 
| 4 | 
            +
              version: 0.1.3
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - ota42y
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2018-12- | 
| 11 | 
            +
            date: 2018-12-18 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bundler
         | 
| @@ -94,6 +94,20 @@ dependencies: | |
| 94 94 | 
             
                - - ">="
         | 
| 95 95 | 
             
                  - !ruby/object:Gem::Version
         | 
| 96 96 | 
             
                    version: '0'
         | 
| 97 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 98 | 
            +
              name: rspec-parameterized
         | 
| 99 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 100 | 
            +
                requirements:
         | 
| 101 | 
            +
                - - ">="
         | 
| 102 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 103 | 
            +
                    version: '0'
         | 
| 104 | 
            +
              type: :development
         | 
| 105 | 
            +
              prerelease: false
         | 
| 106 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 107 | 
            +
                requirements:
         | 
| 108 | 
            +
                - - ">="
         | 
| 109 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 110 | 
            +
                    version: '0'
         | 
| 97 111 | 
             
            description: parser for OpenAPI 3.0 or later
         | 
| 98 112 | 
             
            email:
         | 
| 99 113 | 
             
            - ota42y@gmail.com
         | 
| @@ -114,11 +128,27 @@ files: | |
| 114 128 | 
             
            - bin/setup
         | 
| 115 129 | 
             
            - lib/openapi_parser.rb
         | 
| 116 130 | 
             
            - lib/openapi_parser/concern.rb
         | 
| 131 | 
            +
            - lib/openapi_parser/concerns/expandable.rb
         | 
| 117 132 | 
             
            - lib/openapi_parser/concerns/findable.rb
         | 
| 118 133 | 
             
            - lib/openapi_parser/concerns/parseable.rb
         | 
| 134 | 
            +
            - lib/openapi_parser/config.rb
         | 
| 135 | 
            +
            - lib/openapi_parser/errors.rb
         | 
| 136 | 
            +
            - lib/openapi_parser/parameter_validator.rb
         | 
| 119 137 | 
             
            - lib/openapi_parser/path_item_finder.rb
         | 
| 138 | 
            +
            - lib/openapi_parser/reference_expander.rb
         | 
| 120 139 | 
             
            - lib/openapi_parser/request_operation.rb
         | 
| 121 140 | 
             
            - lib/openapi_parser/schema_validator.rb
         | 
| 141 | 
            +
            - lib/openapi_parser/schema_validators/any_of_validator.rb
         | 
| 142 | 
            +
            - lib/openapi_parser/schema_validators/array_validator.rb
         | 
| 143 | 
            +
            - lib/openapi_parser/schema_validators/base.rb
         | 
| 144 | 
            +
            - lib/openapi_parser/schema_validators/boolean_validator.rb
         | 
| 145 | 
            +
            - lib/openapi_parser/schema_validators/enumable.rb
         | 
| 146 | 
            +
            - lib/openapi_parser/schema_validators/float_validator.rb
         | 
| 147 | 
            +
            - lib/openapi_parser/schema_validators/integer_validator.rb
         | 
| 148 | 
            +
            - lib/openapi_parser/schema_validators/nil_validator.rb
         | 
| 149 | 
            +
            - lib/openapi_parser/schema_validators/object_validator.rb
         | 
| 150 | 
            +
            - lib/openapi_parser/schema_validators/options.rb
         | 
| 151 | 
            +
            - lib/openapi_parser/schema_validators/string_validator.rb
         | 
| 122 152 | 
             
            - lib/openapi_parser/schemas.rb
         | 
| 123 153 | 
             
            - lib/openapi_parser/schemas/base.rb
         | 
| 124 154 | 
             
            - lib/openapi_parser/schemas/classes.rb
         |