openapi_parser 0.1.9 → 0.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dd2a5c6292d86e914f641bf9d2e99b6ef8de9cbc46e5b3196937fc1c691541df
4
- data.tar.gz: 9a6c9a5400e1fffdf12cc0e43fbc89433b7e4b917bd61dfb1c34c613bc17e9f4
3
+ metadata.gz: 778364824149b95c1f94de0e40d94b0cfc7d3743d85942adbc78f7796908323b
4
+ data.tar.gz: 9a352324f2945aab9d75298993cae3585e2577fb742efbae804826a38b5f8c7d
5
5
  SHA512:
6
- metadata.gz: '0093301164855dba5aff9a87cdce0c8d99f85ac5c1c4738c011c850924704313b1fd6f9aee00f01f25e7a125b1d18c3d02659e8594eb6fa1bbd0da84e1bf3734'
7
- data.tar.gz: 23b2105486befe12f39f90a9ea8f893b46a1dd36693782499b497ce1909ddef4a6b2d25da313cc62e3de8bf9a28246a5f140640fd9ff7869526ebfa05ea1a828
6
+ metadata.gz: 9b6899d6db1e2c7e2753e7c023e4abdb2ed99fc90f7fefad00ecd30127a127289c9330ef65e4d7f3931fcc917b07ca05f71625b13cf1d5c5610cfe48c3d767d8
7
+ data.tar.gz: e50ca8c2bc1e85ba4bb793615aaced3d111443348476a57e98278d6ea9492511156228b0a4648d82a92a2513f510f489e52bc7b773f1e3eb1acf39222ebf5a20
@@ -1,5 +1,8 @@
1
1
  ## Unreleased
2
2
 
3
+ ## 0.1.9 (2019-01-02)
4
+ * support header validate (#18)
5
+
3
6
  ## 0.1.9 (2019-01-01)
4
7
  * add strict option (#17)
5
8
 
@@ -2,3 +2,4 @@ require_relative 'concerns/parser'
2
2
  require_relative 'concerns/findable'
3
3
  require_relative 'concerns/expandable'
4
4
  require_relative 'concerns/media_type_selectable'
5
+ require_relative 'concerns/parameter_validatable'
@@ -7,6 +7,7 @@ module OpenAPIParser::MediaTypeSelectable
7
7
  # @return [OpenAPIParser::Schemas::MediaType, nil]
8
8
  def select_media_type_from_content(content_type, content)
9
9
  return nil unless content_type
10
+ return nil unless content
10
11
 
11
12
  if (media_type = content[content_type])
12
13
  return media_type
@@ -0,0 +1,56 @@
1
+ module OpenAPIParser::ParameterValidatable
2
+ # @param [Hash] path_params path parameters
3
+ # @param [OpenAPIParser::SchemaValidator::Options] options request validator options
4
+ def validate_path_params(path_params, options)
5
+ OpenAPIParser::ParameterValidator.validate_parameter(path_parameter_hash, path_params, object_reference, options)
6
+ end
7
+
8
+ # @param [Hash] params parameter hash
9
+ # @param [Hash] headers headers hash
10
+ # @param [OpenAPIParser::SchemaValidator::Options] options request validator options
11
+ def validate_request_parameter(params, headers, options)
12
+ validate_header_parameter(headers, object_reference, options) if options.validate_header
13
+ validate_query_parameter(params, object_reference, options)
14
+ end
15
+
16
+ private
17
+
18
+ # @param [Hash] params query parameter hash
19
+ # @param [String] object_reference
20
+ # @param [OpenAPIParser::SchemaValidator::Options] options request validator options
21
+ def validate_query_parameter(params, object_reference, options)
22
+ OpenAPIParser::ParameterValidator.validate_parameter(query_parameter_hash, params, object_reference, options)
23
+ end
24
+
25
+ # @param [Hash] headers header hash
26
+ # @param [String] object_reference
27
+ # @param [OpenAPIParser::SchemaValidator::Options] options request validator options
28
+ def validate_header_parameter(headers, object_reference, options)
29
+ OpenAPIParser::ParameterValidator.validate_parameter(header_parameter_hash, headers, object_reference, options)
30
+ end
31
+
32
+ def header_parameter_hash
33
+ divided_parameter_hash['header'] || []
34
+ end
35
+
36
+ def path_parameter_hash
37
+ divided_parameter_hash['path'] || []
38
+ end
39
+
40
+ def query_parameter_hash
41
+ divided_parameter_hash['query'] || []
42
+ end
43
+
44
+ # @return [Hash{String => Hash{String => Parameter}}] hash[in][name] => Parameter
45
+ def divided_parameter_hash
46
+ @divided_parameter_hash ||=
47
+ (parameters || []).
48
+ group_by(&:in).
49
+ map { |in_type, params| # rubocop:disable Style/BlockDelimiters
50
+ [
51
+ in_type,
52
+ params.map { |param| [param.name, param] }.to_h,
53
+ ]
54
+ }.to_h
55
+ end
56
+ end
@@ -19,9 +19,15 @@ class OpenAPIParser::Config
19
19
  @config.fetch(:strict_response_validation, false)
20
20
  end
21
21
 
22
+ def validate_header
23
+ @config.fetch(:validate_header, true)
24
+ end
25
+
22
26
  # @return [OpenAPIParser::SchemaValidator::Options]
23
27
  def request_validator_options
24
- @request_validator_options ||= OpenAPIParser::SchemaValidator::Options.new(coerce_value: coerce_value, datetime_coerce_class: datetime_coerce_class)
28
+ @request_validator_options ||= OpenAPIParser::SchemaValidator::Options.new(coerce_value: coerce_value,
29
+ datetime_coerce_class: datetime_coerce_class,
30
+ validate_header: validate_header)
25
31
  end
26
32
 
27
33
  alias_method :request_body_options, :request_validator_options
@@ -29,6 +35,7 @@ class OpenAPIParser::Config
29
35
 
30
36
  # @return [OpenAPIParser::SchemaValidator::ResponseValidateOptions]
31
37
  def response_validate_options
32
- @response_validate_options ||= OpenAPIParser::SchemaValidator::ResponseValidateOptions.new(strict: strict_response_validation)
38
+ @response_validate_options ||= OpenAPIParser::SchemaValidator::ResponseValidateOptions.
39
+ new(strict: strict_response_validation, validate_header: validate_header)
33
40
  end
34
41
  end
@@ -7,13 +7,14 @@ class OpenAPIParser::PathItemFinder
7
7
  @paths.path.each { |path, _path_item_object| @root.register_path_node(path.split('/'), path) }
8
8
  end
9
9
 
10
+ # find operation object and if not exist return nil
10
11
  # @param [String, Symbol] http_method like (get, post .... allow symbol)
11
12
  # @param [String] request_path
12
- # return operation_object, original_path, path_params
13
+ # @return [Result, nil]
13
14
  def operation_object(http_method, request_path)
14
15
  if (path_item_object = @paths.path[request_path])
15
16
  if (op = path_item_object.operation(http_method))
16
- return op, request_path, {} # find no path_params path
17
+ return Result.new(path_item_object, op, request_path, {}) # find no path_params path
17
18
  end
18
19
  end
19
20
 
@@ -21,6 +22,26 @@ class OpenAPIParser::PathItemFinder
21
22
  parse_request_path(http_method, request_path)
22
23
  end
23
24
 
25
+ class Result
26
+ attr_reader :path_item_object, :operation_object, :original_path, :path_params
27
+ # @!attribute [r] path_item_object
28
+ # @return [OpenAPIParser::Schemas::PathItem]
29
+ # @!attribute [r] operation_object
30
+ # @return [OpenAPIParser::Schemas::Operation]
31
+ # @!attribute [r] path_params
32
+ # @return [Hash{String => String}]
33
+ # @!attribute [r] original_path
34
+ # @return [String]
35
+
36
+ def initialize(path_item_object, operation_object, original_path, path_params)
37
+ @path_item_object = path_item_object
38
+ @operation_object = operation_object
39
+ @original_path = original_path
40
+ @path_params = path_params
41
+ end
42
+ end
43
+
44
+ # path tree node
24
45
  class PathNode
25
46
  attr_accessor :full_path, :name
26
47
 
@@ -31,6 +52,8 @@ class OpenAPIParser::PathItemFinder
31
52
  @full_path = nil
32
53
  end
33
54
 
55
+ # @param [Array<string>] splited_path
56
+ # @param [String] full_path
34
57
  def register_path_node(splited_path, full_path)
35
58
  if splited_path.empty?
36
59
  @full_path = full_path
@@ -83,11 +106,12 @@ class OpenAPIParser::PathItemFinder
83
106
 
84
107
  def parse_request_path(http_method, request_path)
85
108
  original_path, path_params = @root.find_full_path(request_path.split('/'))
86
- return nil, nil, {} unless original_path # # can't find
109
+ return nil unless original_path # # can't find
87
110
 
88
111
  path_item_object = @paths.path[original_path]
89
112
  obj = path_item_object.operation(http_method.to_s)
113
+ return nil unless obj
90
114
 
91
- [obj, original_path, path_params]
115
+ Result.new(path_item_object, obj, original_path, path_params)
92
116
  end
93
117
  end
@@ -6,11 +6,10 @@ class OpenAPIParser::RequestOperation
6
6
  # @param [OpenAPIParser::PathItemFinder] path_item_finder
7
7
  # @return [OpenAPIParser::RequestOperation, nil]
8
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)
9
+ result = path_item_finder.operation_object(http_method, request_path)
10
+ return nil unless result
10
11
 
11
- return nil unless operation
12
-
13
- self.new(http_method, original_path, operation, path_params, config)
12
+ self.new(http_method, result, config)
14
13
  end
15
14
  end
16
15
 
@@ -19,19 +18,24 @@ class OpenAPIParser::RequestOperation
19
18
  # @!attribute [r] path_params
20
19
  # @return [Hash{String => String}]
21
20
  # @!attribute [r] config
22
- # # @return [OpenAPIParser::Config]
21
+ # @return [OpenAPIParser::Config]
23
22
  # @!attribute [r] http_method
24
23
  # @return [String]
25
24
  # @!attribute [r] original_path
26
25
  # @return [String]
27
- attr_reader :operation_object, :path_params, :config, :http_method, :original_path
26
+ # @!attribute [r] path_item
27
+ # @return [OpenAPIParser::Schemas::PathItem]
28
+ attr_reader :operation_object, :path_params, :config, :http_method, :original_path, :path_item
28
29
 
30
+ # @param [String] http_method
31
+ # @param [OpenAPIParser::PathItemFinder::Result] result
29
32
  # @param [OpenAPIParser::Config] config
30
- def initialize(http_method, original_path, operation_object, path_params, config)
33
+ def initialize(http_method, result, config)
31
34
  @http_method = http_method.to_s
32
- @original_path = original_path
33
- @operation_object = operation_object
34
- @path_params = path_params || {}
35
+ @original_path = result.original_path
36
+ @operation_object = result.operation_object
37
+ @path_params = result.path_params || {}
38
+ @path_item = result.path_item_object
35
39
  @config = config
36
40
  end
37
41
 
@@ -48,17 +52,34 @@ class OpenAPIParser::RequestOperation
48
52
  operation_object&.validate_request_body(content_type, params, options)
49
53
  end
50
54
 
51
- # @param [String] content_type
52
- # @param [Integer] status_code
53
- # @param [Hash] data
55
+ # @param [OpenAPIParser::RequestOperation::ValidatableResponseBody] response_body
54
56
  # @param [OpenAPIParser::SchemaValidator::ResponseValidateOptions] response_validate_options
55
- def validate_response_body(status_code, content_type, data, response_validate_options = nil)
57
+ def validate_response_body(response_body, response_validate_options = nil)
56
58
  response_validate_options ||= config.response_validate_options
57
- operation_object&.validate_response_body(status_code, content_type, data, response_validate_options)
59
+
60
+ operation_object&.validate_response(response_body, response_validate_options)
58
61
  end
59
62
 
60
- def validate_request_parameter(params, options = nil)
63
+ # @param [Hash] params parameter hash
64
+ # @param [Hash] headers headers hash
65
+ # @param [OpenAPIParser::SchemaValidator::Options] options request validator options
66
+ def validate_request_parameter(params, headers, options = nil)
61
67
  options ||= config.request_validator_options
62
- operation_object&.validate_request_parameter(params, options)
68
+ path_item&.validate_request_parameter(params, headers, options)
69
+ operation_object&.validate_request_parameter(params, headers, options)
70
+ end
71
+
72
+ class ValidatableResponseBody
73
+ attr_reader :status_code, :response_data, :headers
74
+
75
+ def initialize(status_code, response_data, headers)
76
+ @status_code = status_code
77
+ @response_data = response_data
78
+ @headers = headers
79
+ end
80
+
81
+ def content_type
82
+ headers['Content-Type'].to_s.split(';').first.to_s
83
+ end
63
84
  end
64
85
  end
@@ -4,11 +4,14 @@ class OpenAPIParser::SchemaValidator
4
4
  # @return [Boolean] coerce value option on/off
5
5
  # @!attribute [r] datetime_coerce_class
6
6
  # @return [Object, nil] coerce datetime string by this Object class
7
- attr_reader :coerce_value, :datetime_coerce_class
7
+ # @!attribute [r] validate_header
8
+ # @return [Boolean] validate header or not
9
+ attr_reader :coerce_value, :datetime_coerce_class, :validate_header
8
10
 
9
- def initialize(coerce_value: nil, datetime_coerce_class: nil)
11
+ def initialize(coerce_value: nil, datetime_coerce_class: nil, validate_header: true)
10
12
  @coerce_value = coerce_value
11
13
  @datetime_coerce_class = datetime_coerce_class
14
+ @validate_header = validate_header
12
15
  end
13
16
  end
14
17
 
@@ -16,10 +19,11 @@ class OpenAPIParser::SchemaValidator
16
19
  class ResponseValidateOptions
17
20
  # @!attribute [r] strict
18
21
  # @return [Boolean] validate by strict (when not exist definition, raise error)
19
- attr_reader :strict
22
+ attr_reader :strict, :validate_header
20
23
 
21
- def initialize(strict: false)
24
+ def initialize(strict: false, validate_header: true)
22
25
  @strict = strict
26
+ @validate_header = validate_header
23
27
  end
24
28
  end
25
29
  end
@@ -13,3 +13,4 @@ require_relative 'schemas/responses'
13
13
  require_relative 'schemas/components'
14
14
  require_relative 'schemas/media_type'
15
15
  require_relative 'schemas/schema'
16
+ require_relative 'schemas/header'
@@ -14,4 +14,5 @@ module OpenAPIParser::Schemas
14
14
  class MediaType < Base; end
15
15
  class Schema < Base; end
16
16
  class Components < Base; end
17
+ class Header < Base; end
17
18
  end
@@ -1,5 +1,4 @@
1
1
  # TODO: examples
2
- # TODO: headers
3
2
  # TODO: securitySchemes
4
3
  # TODO: links
5
4
  # TODO: callbacks
@@ -21,5 +20,9 @@ module OpenAPIParser::Schemas
21
20
  # @!attribute [r] request_bodies
22
21
  # @return [Hash{String => RequestBody}, nil]
23
22
  openapi_attr_hash_object :request_bodies, RequestBody, reference: true, schema_key: :requestBodies
23
+
24
+ # @!attribute [r] headers
25
+ # @return [Hash{String => Header}, nil] header objects
26
+ openapi_attr_hash_object :headers, Header, reference: true
24
27
  end
25
28
  end
@@ -0,0 +1,18 @@
1
+ module OpenAPIParser::Schemas
2
+ class Header < Base
3
+ openapi_attr_values :description, :required, :deprecated, :style, :explode, :example
4
+
5
+ openapi_attr_value :allow_empty_value, schema_key: :allowEmptyValue
6
+ openapi_attr_value :allow_reserved, schema_key: :allowReserved
7
+
8
+ # @!attribute [r] schema
9
+ # @return [Schema, Reference, nil]
10
+ openapi_attr_object :schema, Schema, reference: true
11
+
12
+ # validate by schema
13
+ # @param [Object] value
14
+ def validate(value)
15
+ OpenAPIParser::SchemaValidator.validate(value, schema, OpenAPIParser::SchemaValidator::Options.new)
16
+ end
17
+ end
18
+ end
@@ -5,6 +5,8 @@
5
5
 
6
6
  module OpenAPIParser::Schemas
7
7
  class Operation < Base
8
+ include OpenAPIParser::ParameterValidatable
9
+
8
10
  openapi_attr_values :tags, :summary, :description, :deprecated
9
11
 
10
12
  openapi_attr_value :operation_id, schema_key: :operationId
@@ -23,37 +25,10 @@ module OpenAPIParser::Schemas
23
25
  request_body&.validate_request_body(content_type, params, options)
24
26
  end
25
27
 
26
- # @param [String] content_type
27
- # @param [Integer] status_code
28
- # @param [Hash] data
28
+ # @param [OpenAPIParser::RequestOperation::ValidatableResponseBody] response_body
29
29
  # @param [OpenAPIParser::SchemaValidator::ResponseValidateOptions] response_validate_options
30
- def validate_response_body(status_code, content_type, data, response_validate_options)
31
- responses&.validate_response_body(status_code, content_type, data, response_validate_options)
32
- end
33
-
34
- # @param [OpenAPIParser::SchemaValidator::Options] options
35
- def validate_request_parameter(params, options)
36
- OpenAPIParser::ParameterValidator.validate_parameter(query_parameter_hash, params, object_reference, options)
30
+ def validate_response(response_body, response_validate_options)
31
+ responses&.validate(response_body, response_validate_options)
37
32
  end
38
-
39
- def validate_path_params(path_params, options)
40
- OpenAPIParser::ParameterValidator.validate_parameter(path_parameter_hash, path_params, object_reference, options)
41
- end
42
-
43
- private
44
-
45
- def path_parameter_hash
46
- @path_parameter_hash ||= (parameters || []).
47
- select(&:in_path?).
48
- map { |param| [param.name, param] }.
49
- to_h
50
- end
51
-
52
- def query_parameter_hash
53
- @query_parameter_hash ||= (parameters || []).
54
- select(&:in_query?).
55
- map { |param| [param.name, param] }.
56
- to_h
57
- end
58
33
  end
59
34
  end
@@ -11,14 +11,6 @@ module OpenAPIParser::Schemas
11
11
  # @return [Schema, Reference, nil]
12
12
  openapi_attr_object :schema, Schema, reference: true
13
13
 
14
- def in_query?
15
- self.in == 'query'
16
- end
17
-
18
- def in_path?
19
- self.in == 'path'
20
- end
21
-
22
14
  # @return [Object] coerced or original params
23
15
  # @param [OpenAPIParser::SchemaValidator::Options] options
24
16
  def validate_params(params, options)
@@ -3,6 +3,8 @@
3
3
 
4
4
  module OpenAPIParser::Schemas
5
5
  class PathItem < Base
6
+ include OpenAPIParser::ParameterValidatable
7
+
6
8
  openapi_attr_values :summary, :description
7
9
 
8
10
  openapi_attr_objects :get, :put, :post, :delete, :options, :head, :patch, :trace, Operation
@@ -1,4 +1,3 @@
1
- # TODO: headers
2
1
  # TODO: links
3
2
 
4
3
  module OpenAPIParser::Schemas
@@ -11,11 +10,16 @@ module OpenAPIParser::Schemas
11
10
  # @return [Hash{String => MediaType}, nil] content_type to MediaType hash
12
11
  openapi_attr_hash_object :content, MediaType, reference: false
13
12
 
14
- # @param [String] content_type
15
- # @param [Hash] params
13
+ # @!attribute [r] headers
14
+ # @return [Hash{String => Header}, nil] header string to Header
15
+ openapi_attr_hash_object :headers, Header, reference: true
16
+
17
+ # @param [OpenAPIParser::RequestOperation::ValidatableResponseBody] response_body
16
18
  # @param [OpenAPIParser::SchemaValidator::ResponseValidateOptions] response_validate_options
17
- def validate_parameter(content_type, params, response_validate_options)
18
- media_type = select_media_type(content_type)
19
+ def validate(response_body, response_validate_options)
20
+ validate_header(response_body.headers) if response_validate_options.validate_header
21
+
22
+ media_type = select_media_type(response_body.content_type)
19
23
  unless media_type
20
24
  raise ::OpenAPIParser::NotExistContentTypeDefinition, object_reference if response_validate_options.strict
21
25
 
@@ -23,7 +27,7 @@ module OpenAPIParser::Schemas
23
27
  end
24
28
 
25
29
  options = ::OpenAPIParser::SchemaValidator::Options.new # response validator not support any options
26
- media_type.validate_parameter(params, options)
30
+ media_type.validate_parameter(response_body.response_data, options)
27
31
  end
28
32
 
29
33
  # select media type by content_type (consider wild card definition)
@@ -32,5 +36,19 @@ module OpenAPIParser::Schemas
32
36
  def select_media_type(content_type)
33
37
  select_media_type_from_content(content_type, content)
34
38
  end
39
+
40
+ private
41
+
42
+ # @param [Hash] response_headers
43
+ def validate_header(response_headers)
44
+ return unless headers
45
+
46
+ headers.each do |k, v|
47
+ h = response_headers[k]
48
+ next unless h
49
+
50
+ v.validate(h)
51
+ end
52
+ end
35
53
  end
36
54
  end
@@ -13,15 +13,14 @@ module OpenAPIParser::Schemas
13
13
  # validate params data by definition
14
14
  # find response object by status_code and content_type
15
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
16
+ # @param [OpenAPIParser::RequestOperation::ValidatableResponseBody] response_body
19
17
  # @param [OpenAPIParser::SchemaValidator::ResponseValidateOptions] response_validate_options
20
- def validate_response_body(status_code, content_type, params, response_validate_options)
18
+ def validate(response_body, response_validate_options)
21
19
  return nil unless response
22
20
 
23
- if (res = find_response_object(status_code))
24
- return res.validate_parameter(content_type, params, response_validate_options)
21
+ if (res = find_response_object(response_body.status_code))
22
+
23
+ return res.validate(response_body, response_validate_options)
25
24
  end
26
25
 
27
26
  raise ::OpenAPIParser::NotExistStatusCodeDefinition, object_reference if response_validate_options.strict
@@ -1,3 +1,3 @@
1
1
  module OpenAPIParser
2
- VERSION = '0.1.9'.freeze
2
+ VERSION = '0.2.0'.freeze
3
3
  end
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.9
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ota42y
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-01-01 00:00:00.000000000 Z
11
+ date: 2019-01-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -147,6 +147,7 @@ files:
147
147
  - lib/openapi_parser/concerns/expandable.rb
148
148
  - lib/openapi_parser/concerns/findable.rb
149
149
  - lib/openapi_parser/concerns/media_type_selectable.rb
150
+ - lib/openapi_parser/concerns/parameter_validatable.rb
150
151
  - lib/openapi_parser/concerns/parser.rb
151
152
  - lib/openapi_parser/concerns/parser/core.rb
152
153
  - lib/openapi_parser/concerns/parser/hash.rb
@@ -185,6 +186,7 @@ files:
185
186
  - lib/openapi_parser/schemas/base.rb
186
187
  - lib/openapi_parser/schemas/classes.rb
187
188
  - lib/openapi_parser/schemas/components.rb
189
+ - lib/openapi_parser/schemas/header.rb
188
190
  - lib/openapi_parser/schemas/media_type.rb
189
191
  - lib/openapi_parser/schemas/openapi.rb
190
192
  - lib/openapi_parser/schemas/operation.rb