openapi_parser 0.1.9 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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