openapi_parser 0.11.0 → 0.13.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 +4 -4
- data/.gitignore +4 -1
- data/.travis.yml +4 -3
- data/CHANGELOG.md +18 -0
- data/lib/openapi_parser.rb +4 -1
- data/lib/openapi_parser/concerns/findable.rb +10 -5
- data/lib/openapi_parser/errors.rb +16 -16
- data/lib/openapi_parser/path_item_finder.rb +42 -7
- data/lib/openapi_parser/schema_validators/boolean_validator.rb +5 -0
- data/lib/openapi_parser/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9afe7e0164ddcad6c8a8fbb6d57e0514e32df10d014bc642b88fa3473f1f8d74
|
4
|
+
data.tar.gz: cefb18a632f4a16dd948fe2e82fadfc0236a159af2406fdcb52db50ef6dc980e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fb0397b9251edac7e3bfb15e30041d5945a466c21b6671183eaec8491a372730e2f76101af71efbc7c07c66345353c260983acfb69d80f2b066c35c71207a076
|
7
|
+
data.tar.gz: 5a58f4b47946ca9c376dcce3c5be34de998a2bc3d59ee4321e2e7f0425c7cdf6b809ff9eb3a103fe099a849210def6c362431628610fdde137b3b79157a32849
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
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
|
data/lib/openapi_parser.rb
CHANGED
@@ -78,7 +78,10 @@ module OpenAPIParser
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def parse_yaml(content)
|
81
|
-
|
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[
|
16
|
+
if (obj = @find_object_cache[unescaped_reference])
|
14
17
|
return obj
|
15
18
|
end
|
16
19
|
|
17
|
-
if (child = _openapi_all_child_objects[
|
18
|
-
@find_object_cache[
|
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(
|
24
|
-
@find_object_cache[
|
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
|
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
|
-
|
74
|
-
|
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
|
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
|
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[
|
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
|
|
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.
|
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:
|
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.
|
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: []
|