openapi_parser 0.11.0 → 0.13.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: c94d0bbb5e44314e9cde71c23587355496214b1fdf6ca2e3bf43f404087b6220
4
- data.tar.gz: be8205b97559da91e85613df31c2ac0e060116046532e4285eb01127c0303eae
3
+ metadata.gz: 9afe7e0164ddcad6c8a8fbb6d57e0514e32df10d014bc642b88fa3473f1f8d74
4
+ data.tar.gz: cefb18a632f4a16dd948fe2e82fadfc0236a159af2406fdcb52db50ef6dc980e
5
5
  SHA512:
6
- metadata.gz: a844336ca5d80573478d7e35d6978881c8d0581e2757584e227781c5b523e1f181f5403c4efb4047df3a9c519043ab0513bbaf5df83acff12d54f0d2c19874a2
7
- data.tar.gz: 406ad0fc2ad51af48b56ba1bf2ace1cac8b920adb85615e160e901aacbacf58c94a02cf4c737cf0601a6bab120bc2c51b3d7cd3f9da0295138edbc63bf7cf8ae
6
+ metadata.gz: fb0397b9251edac7e3bfb15e30041d5945a466c21b6671183eaec8491a372730e2f76101af71efbc7c07c66345353c260983acfb69d80f2b066c35c71207a076
7
+ data.tar.gz: 5a58f4b47946ca9c376dcce3c5be34de998a2bc3d59ee4321e2e7f0425c7cdf6b809ff9eb3a103fe099a849210def6c362431628610fdde137b3b79157a32849
data/.gitignore CHANGED
@@ -7,6 +7,9 @@
7
7
  /spec/reports/
8
8
  /tmp/
9
9
 
10
+ # RubyMine
11
+ .idea
12
+
10
13
  # rspec failure tracking
11
14
  .rspec_status
12
- Gemfile.lock
15
+ Gemfile.lock
data/.travis.yml CHANGED
@@ -7,9 +7,10 @@ language: ruby
7
7
  rvm:
8
8
  - 2.3.8
9
9
  - 2.4.10
10
- - 2.5.8
11
- - 2.6.6
12
- - 2.7.1
10
+ - 2.5.9
11
+ - 2.6.7
12
+ - 2.7.3
13
+ - 3.0.1
13
14
  - ruby-head
14
15
 
15
16
  cache: bundler
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  ## Unreleased
2
2
 
3
+ ## 0.13.0 (2021-05-01)
4
+ * Fix a problem with remote reference to path items which have path parameters #95
5
+ * Support enum for booleans. #104
6
+
7
+ ## 0.12.1 (2020-08-27)
8
+ * Use CGI.unescape (warning fix) #92
9
+
10
+ ## 0.12.0 (2020-08-26)
11
+ * Find path by extracted params than path length #84
12
+ * Unescape ref URI before lookup in OpenAPIParser::Findable #85
13
+ * Improved path parameter matching code to allow file extensions, multiple parameters inside one path element, etc #90
14
+
15
+ ## 0.11.2 (2020-05-23)
16
+ * Allow date and time content in YAML #81
17
+
18
+ ## 0.11.1 (2020-05-09)
19
+ * fix too many warning
20
+
3
21
  ## 0.11.0 (2020-05-09)
4
22
  * Add committee friendly interface to use remote references. #74
5
23
  * Prevent SystemStackError on recursive schema reference #76
@@ -78,7 +78,10 @@ module OpenAPIParser
78
78
  end
79
79
 
80
80
  def parse_yaml(content)
81
- Psych.safe_load(content)
81
+ # FIXME: when drop ruby 2.5, we should use permitted_classes
82
+ (Gem::Version.create(RUBY_VERSION) < Gem::Version.create("2.6.0")) ?
83
+ Psych.safe_load(content, [Date, Time]) :
84
+ Psych.safe_load(content, permitted_classes: [Date, Time])
82
85
  end
83
86
 
84
87
  def parse_json(content)
@@ -1,3 +1,4 @@
1
+ require 'cgi'
1
2
  require 'uri'
2
3
 
3
4
  module OpenAPIParser::Findable
@@ -9,19 +10,21 @@ module OpenAPIParser::Findable
9
10
  return find_remote_object(reference) if remote_reference
10
11
  return nil unless reference.start_with?(object_reference)
11
12
 
13
+ unescaped_reference = CGI.unescape(reference)
14
+
12
15
  @find_object_cache = {} unless defined? @find_object_cache
13
- if (obj = @find_object_cache[reference])
16
+ if (obj = @find_object_cache[unescaped_reference])
14
17
  return obj
15
18
  end
16
19
 
17
- if (child = _openapi_all_child_objects[reference])
18
- @find_object_cache[reference] = child
20
+ if (child = _openapi_all_child_objects[unescaped_reference])
21
+ @find_object_cache[unescaped_reference] = child
19
22
  return child
20
23
  end
21
24
 
22
25
  _openapi_all_child_objects.values.each do |c|
23
- if (obj = c.find_object(reference))
24
- @find_object_cache[reference] = obj
26
+ if (obj = c.find_object(unescaped_reference))
27
+ @find_object_cache[unescaped_reference] = obj
25
28
  return obj
26
29
  end
27
30
  end
@@ -30,6 +33,8 @@ module OpenAPIParser::Findable
30
33
  end
31
34
 
32
35
  def purge_object_cache
36
+ @purged = false unless defined? @purged
37
+
33
38
  return if @purged
34
39
 
35
40
  @find_object_cache = {}
@@ -13,7 +13,7 @@ module OpenAPIParser
13
13
  end
14
14
 
15
15
  def message
16
- "#{@reference} expected #{@type}, but received #{@data.class}: #{@data}"
16
+ "#{@reference} expected #{@type}, but received #{@data.class}: #{@data.inspect}"
17
17
  end
18
18
 
19
19
  class << self
@@ -73,7 +73,7 @@ module OpenAPIParser
73
73
  end
74
74
 
75
75
  def message
76
- "discriminator propertyName #{@key} does not exist in value #{@value} in #{@reference}"
76
+ "discriminator propertyName #{@key} does not exist in value #{@value.inspect} in #{@reference}"
77
77
  end
78
78
  end
79
79
 
@@ -84,7 +84,7 @@ module OpenAPIParser
84
84
  end
85
85
 
86
86
  def message
87
- "#{@value} isn't one of in #{@reference}"
87
+ "#{@value.inspect} isn't one of in #{@reference}"
88
88
  end
89
89
  end
90
90
 
@@ -95,7 +95,7 @@ module OpenAPIParser
95
95
  end
96
96
 
97
97
  def message
98
- "#{@value} isn't any of in #{@reference}"
98
+ "#{@value.inspect} isn't any of in #{@reference}"
99
99
  end
100
100
  end
101
101
 
@@ -106,7 +106,7 @@ module OpenAPIParser
106
106
  end
107
107
 
108
108
  def message
109
- "#{@value} isn't include enum in #{@reference}"
109
+ "#{@value.inspect} isn't part of the enum in #{@reference}"
110
110
  end
111
111
  end
112
112
 
@@ -117,7 +117,7 @@ module OpenAPIParser
117
117
  end
118
118
 
119
119
  def message
120
- "#{@reference} #{@value} is less than minimum value"
120
+ "#{@reference} #{@value.inspect} is less than minimum value"
121
121
  end
122
122
  end
123
123
 
@@ -128,7 +128,7 @@ module OpenAPIParser
128
128
  end
129
129
 
130
130
  def message
131
- "#{@reference} #{@value} cannot be less than or equal to exclusive minimum value"
131
+ "#{@reference} #{@value.inspect} cannot be less than or equal to exclusive minimum value"
132
132
  end
133
133
  end
134
134
 
@@ -139,7 +139,7 @@ module OpenAPIParser
139
139
  end
140
140
 
141
141
  def message
142
- "#{@reference} #{@value} is more than maximum value"
142
+ "#{@reference} #{@value.inspect} is more than maximum value"
143
143
  end
144
144
  end
145
145
 
@@ -150,7 +150,7 @@ module OpenAPIParser
150
150
  end
151
151
 
152
152
  def message
153
- "#{@reference} #{@value} cannot be more than or equal to exclusive maximum value"
153
+ "#{@reference} #{@value.inspect} cannot be more than or equal to exclusive maximum value"
154
154
  end
155
155
  end
156
156
 
@@ -163,7 +163,7 @@ module OpenAPIParser
163
163
  end
164
164
 
165
165
  def message
166
- "#{@reference} pattern #{@pattern} does not match value: #{@value}#{@example ? ", example: #{@example}" : ""}"
166
+ "#{@reference} pattern #{@pattern} does not match value: #{@value.inspect}#{@example ? ", example: #{@example}" : ""}"
167
167
  end
168
168
  end
169
169
 
@@ -174,7 +174,7 @@ module OpenAPIParser
174
174
  end
175
175
 
176
176
  def message
177
- "#{@reference} email address format does not match value: #{@value}"
177
+ "#{@reference} email address format does not match value: #{@value.inspect}"
178
178
  end
179
179
  end
180
180
 
@@ -185,7 +185,7 @@ module OpenAPIParser
185
185
  end
186
186
 
187
187
  def message
188
- "#{@reference} Value: #{@value} is not conformant with UUID format"
188
+ "#{@reference} Value: #{@value.inspect} is not conformant with UUID format"
189
189
  end
190
190
  end
191
191
 
@@ -208,7 +208,7 @@ module OpenAPIParser
208
208
  end
209
209
 
210
210
  def message
211
- "#{@reference} #{@value} is longer than max length"
211
+ "#{@reference} #{@value.inspect} is longer than max length"
212
212
  end
213
213
  end
214
214
 
@@ -219,7 +219,7 @@ module OpenAPIParser
219
219
  end
220
220
 
221
221
  def message
222
- "#{@reference} #{@value} is shorter than min length"
222
+ "#{@reference} #{@value.inspect} is shorter than min length"
223
223
  end
224
224
  end
225
225
 
@@ -230,7 +230,7 @@ module OpenAPIParser
230
230
  end
231
231
 
232
232
  def message
233
- "#{@reference} #{@value} contains more than max items"
233
+ "#{@reference} #{@value.inspect} contains more than max items"
234
234
  end
235
235
  end
236
236
 
@@ -241,7 +241,7 @@ module OpenAPIParser
241
241
  end
242
242
 
243
243
  def message
244
- "#{@reference} #{@value} contains fewer than min items"
244
+ "#{@reference} #{@value.inspect} contains fewer than min items"
245
245
  end
246
246
  end
247
247
  end
@@ -38,7 +38,41 @@ class OpenAPIParser::PathItemFinder
38
38
  end
39
39
  end
40
40
 
41
+ def parse_path_parameters(schema_path, request_path)
42
+ parameters = path_parameters(schema_path)
43
+ return nil if parameters.empty?
44
+
45
+ # If there are regex special characters in the path, the regex will
46
+ # be too permissive, so escape the non-parameter parts.
47
+ components = []
48
+ unprocessed = schema_path.dup
49
+ parameters.each do |parameter|
50
+ parts = unprocessed.partition(parameter)
51
+ components << Regexp.escape(parts[0]) unless parts[0] == ''
52
+ components << "(?<#{param_name(parameter)}>.+)"
53
+ unprocessed = parts[2]
54
+ end
55
+ components << Regexp.escape(unprocessed) unless unprocessed == ''
56
+
57
+ regex = components.join('')
58
+ matches = request_path.match(regex)
59
+ return nil unless matches
60
+
61
+ # Match up the captured names with the captured values as a hash
62
+ matches.names.zip(matches.captures).to_h
63
+ end
64
+
41
65
  private
66
+ def path_parameters(schema_path)
67
+ # OAS3 follows a RFC6570 subset for URL templates
68
+ # https://swagger.io/docs/specification/serialization/#uri-templates
69
+ # A URL template param can be preceded optionally by a "." or ";", and can be succeeded optionally by a "*";
70
+ # this regex returns a match of the full parameter name with all of these modifiers. Ex: {;id*}
71
+ parameters = schema_path.scan(/(\{[\.;]*[^\{\*\}]+\**\})/)
72
+ # The `String#scan` method returns an array of arrays; we want an array of strings
73
+ parameters.collect { |param| param[0] }
74
+ end
75
+
42
76
  # check if there is a identical path in the schema (without any param)
43
77
  def matches_directly?(request_path, http_method)
44
78
  @paths.path[request_path]&.operation(http_method)
@@ -70,8 +104,9 @@ class OpenAPIParser::PathItemFinder
70
104
  splitted_request_path.zip(splitted_schema_path).reduce({}) do |result, zip_item|
71
105
  request_path_item, schema_path_item = zip_item
72
106
 
73
- if path_template?(schema_path_item)
74
- result[param_name(schema_path_item)] = request_path_item
107
+ params = parse_path_parameters(schema_path_item, request_path_item)
108
+ if params
109
+ result.merge!(params)
75
110
  else
76
111
  return if schema_path_item != request_path_item
77
112
  end
@@ -80,7 +115,7 @@ class OpenAPIParser::PathItemFinder
80
115
  end
81
116
  end
82
117
 
83
- # find all matching patchs with parameters extracted
118
+ # find all matching paths with parameters extracted
84
119
  # EXAMPLE:
85
120
  # [
86
121
  # ['/user/{id}/edit', { 'id' => 1 }],
@@ -94,23 +129,23 @@ class OpenAPIParser::PathItemFinder
94
129
  splitted_schema_path = path.split('/')
95
130
 
96
131
  next result if different_depth_or_method?(splitted_schema_path, splitted_request_path, path_item, http_method)
97
-
132
+
98
133
  extracted_params = extract_params(splitted_request_path, splitted_schema_path)
99
134
  result << [path, extracted_params] if extracted_params
100
135
  result
101
136
  end
102
137
  end
103
138
 
104
- # find mathing path and extract params
139
+ # find matching path and extract params
105
140
  # EXAMPLE: find_path_and_params('get', '/user/1') => ['/user/{id}', { 'id' => 1 }]
106
141
  def find_path_and_params(http_method, request_path)
107
142
  return [request_path, {}] if matches_directly?(request_path, http_method)
108
-
143
+
109
144
  matching = matching_paths_with_params(request_path, http_method)
110
145
 
111
146
  # if there are many matching paths, return the one with the smallest number of params
112
147
  # (prefer /user/{id}/action over /user/{param_1}/{param_2} )
113
- matching.min_by { |match| match[0].size }
148
+ matching.min_by { |match| match[1].size }
114
149
  end
115
150
 
116
151
  def parse_request_path(http_method, request_path)
@@ -1,5 +1,7 @@
1
1
  class OpenAPIParser::SchemaValidator
2
2
  class BooleanValidator < Base
3
+ include ::OpenAPIParser::SchemaValidator::Enumable
4
+
3
5
  TRUE_VALUES = ['true', '1'].freeze
4
6
  FALSE_VALUES = ['false', '0'].freeze
5
7
 
@@ -8,6 +10,9 @@ class OpenAPIParser::SchemaValidator
8
10
 
9
11
  return OpenAPIParser::ValidateError.build_error_result(value, schema) unless value.kind_of?(TrueClass) || value.kind_of?(FalseClass)
10
12
 
13
+ value, err = check_enum_include(value, schema)
14
+ return [nil, err] if err
15
+
11
16
  [value, nil]
12
17
  end
13
18
 
@@ -1,3 +1,3 @@
1
1
  module OpenAPIParser
2
- VERSION = '0.11.0'.freeze
2
+ VERSION = '0.13.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.11.0
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ota42y
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-09 00:00:00.000000000 Z
11
+ date: 2021-05-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -207,7 +207,7 @@ homepage: https://github.com/ota42y/openapi_parser
207
207
  licenses:
208
208
  - MIT
209
209
  metadata: {}
210
- post_install_message:
210
+ post_install_message:
211
211
  rdoc_options: []
212
212
  require_paths:
213
213
  - lib
@@ -222,8 +222,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
222
222
  - !ruby/object:Gem::Version
223
223
  version: '0'
224
224
  requirements: []
225
- rubygems_version: 3.1.2
226
- signing_key:
225
+ rubygems_version: 3.2.3
226
+ signing_key:
227
227
  specification_version: 4
228
228
  summary: OpenAPI3 parser
229
229
  test_files: []