openapi_parser 0.9.0 → 0.10.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: e01493b04243073a1fec0acaa56db780076e3c30f3a64534da419bd745408b87
4
- data.tar.gz: 1e57cd341560e800018fa82bbc4801910bbdfdf4a580ccbdaaa63fa0fe442d4a
3
+ metadata.gz: 98afa3c7fb754859a594373659d18ebb81483581c948621d0ea050c360da38ec
4
+ data.tar.gz: 9cf7b695875b6ca55a89a3d5e1a288381d39e203c5fbb469beeb7465232ff0a5
5
5
  SHA512:
6
- metadata.gz: 28182a2367a7ff7314f0c8b35c51d321ce7ce6e9238cd72c83bd57e3cb1970bc9000e19b6a725a47b14ed6262befff61dd325106f9a1389bd72ffa7de7230fe2
7
- data.tar.gz: 0c5560de5b4579933d135d0046a3ae4aaa3e701d83779ff8efd0713023ad5f6d6f37b485f41fa9eb3c3ac5b26c1118afe724d2b9787440e1bfd229c6f0d823a9
6
+ metadata.gz: ddc32d47e0072b78f4790a6b6fa031eab103bb4665d5c0cfe4e7ac2ac9b2e04a048a82f4ddefd40fd112221e389cd86568ac67c3ca9db6f46ae4b9f8ece23c8a
7
+ data.tar.gz: bdd2fdeaec224eaecdde6088abc7eb69513a4ab9e2afffbf23a6a21f9e13a640bddaf6bd7fbbaab16dff588c021bc12296aefd01b1efcb28908f33f8b263f9ad
@@ -1,5 +1,9 @@
1
1
  ## Unreleased
2
2
 
3
+ ## 0.10.0 (2020-04-01)
4
+ * Support $ref to objects in other OpenAPI yaml files #66
5
+ * Allow $ref for path item objects #71
6
+
3
7
  ## 0.9.0 (2020-03-22)
4
8
  * Added support for validating UUID formatted strings #67
5
9
 
@@ -1,4 +1,9 @@
1
+ require 'uri'
1
2
  require 'time'
3
+ require 'json'
4
+ require 'psych'
5
+ require 'pathname'
6
+ require 'open-uri'
2
7
 
3
8
  require 'openapi_parser/version'
4
9
  require 'openapi_parser/config'
@@ -13,14 +18,67 @@ require 'openapi_parser/reference_expander'
13
18
 
14
19
  module OpenAPIParser
15
20
  class << self
21
+ # Load schema yaml object. Uri is not set for returned schema.
16
22
  # @return [OpenAPIParser::Schemas::OpenAPI]
17
23
  def parse(schema, config = {})
18
- c = Config.new(config)
19
- root = Schemas::OpenAPI.new(schema, c)
24
+ load_hash(schema, config: Config.new(config), uri: nil, schema_registry: {})
25
+ end
26
+
27
+ # Load schema in specified filepath. If file path is relative, it is resolved using working directory.
28
+ # @return [OpenAPIParser::Schemas::OpenAPI]
29
+ def load(filepath, config = {})
30
+ path = Pathname.new(filepath)
31
+ path = Pathname.getwd + path if path.relative?
32
+ load_uri(URI.join("file:///", path.to_s), config: Config.new(config), schema_registry: {})
33
+ end
20
34
 
21
- OpenAPIParser::ReferenceExpander.expand(root) if c.expand_reference
35
+ # Load schema located by the passed uri. Uri must be absolute.
36
+ # @return [OpenAPIParser::Schemas::OpenAPI]
37
+ def load_uri(uri, config:, schema_registry:)
38
+ # Open-uri doesn't open file scheme uri, so we try to open file path directly
39
+ # File scheme uri which points to a remote file is not supported.
40
+ content = if uri.scheme == 'file'
41
+ open(uri.path, &:read)
42
+ else
43
+ uri.open(&:read)
44
+ end
22
45
 
23
- root
46
+ extension = Pathname.new(uri.path).extname
47
+ load_hash(parse_file(content, extension), config: config, uri: uri, schema_registry: schema_registry)
24
48
  end
49
+
50
+ private
51
+
52
+ def parse_file(content, extension)
53
+ case extension.downcase
54
+ when '.yaml', '.yml'
55
+ parse_yaml(content)
56
+ when '.json'
57
+ parse_json(content)
58
+ else
59
+ # When extension is something we don't know, try to parse as json first. If it fails, parse as yaml
60
+ begin
61
+ parse_json(content)
62
+ rescue JSON::ParserError
63
+ parse_yaml(content)
64
+ end
65
+ end
66
+ end
67
+
68
+ def parse_yaml(content)
69
+ Psych.safe_load(content)
70
+ end
71
+
72
+ def parse_json(content)
73
+ JSON.parse(content)
74
+ end
75
+
76
+ def load_hash(hash, config:, uri:, schema_registry:)
77
+ root = Schemas::OpenAPI.new(hash, config, uri: uri, schema_registry: schema_registry)
78
+
79
+ OpenAPIParser::ReferenceExpander.expand(root) if config.expand_reference
80
+
81
+ root
82
+ end
25
83
  end
26
84
  end
@@ -1,9 +1,13 @@
1
+ require 'uri'
2
+
1
3
  module OpenAPIParser::Findable
2
4
  # @param [String] reference
3
5
  # @return [OpenAPIParser::Findable]
4
6
  def find_object(reference)
5
- return nil unless reference.start_with?(object_reference)
6
7
  return self if object_reference == reference
8
+ remote_reference = !reference.start_with?('#')
9
+ return find_remote_object(reference) if remote_reference
10
+ return nil unless reference.start_with?(object_reference)
7
11
 
8
12
  @find_object_cache = {} unless defined? @find_object_cache
9
13
  if (obj = @find_object_cache[reference])
@@ -30,4 +34,13 @@ module OpenAPIParser::Findable
30
34
 
31
35
  _openapi_all_child_objects.values.each(&:purge_object_cache)
32
36
  end
37
+
38
+ private
39
+
40
+ def find_remote_object(reference)
41
+ reference_uri = URI(reference)
42
+ fragment = reference_uri.fragment
43
+ reference_uri.fragment = nil
44
+ root.load_another_schema(reference_uri)&.find_object("##{fragment}")
45
+ end
33
46
  end
@@ -178,6 +178,17 @@ module OpenAPIParser
178
178
  end
179
179
  end
180
180
 
181
+ class InvalidUUIDFormat < OpenAPIError
182
+ def initialize(value, reference)
183
+ super(reference)
184
+ @value = value
185
+ end
186
+
187
+ def message
188
+ "#{@reference} Value: #{@value} is not conformant with UUID format"
189
+ end
190
+ end
191
+
181
192
  class NotExistStatusCodeDefinition < OpenAPIError
182
193
  def message
183
194
  "#{@reference} status code definition does not exist"
@@ -27,6 +27,9 @@ class OpenAPIParser::SchemaValidator
27
27
  value, err = validate_email_format(value, schema)
28
28
  return [nil, err] if err
29
29
 
30
+ value, err = validate_uuid_format(value, schema)
31
+ return [nil, err] if err
32
+
30
33
  [value, nil]
31
34
  end
32
35
 
@@ -75,5 +78,13 @@ class OpenAPIParser::SchemaValidator
75
78
 
76
79
  return [nil, OpenAPIParser::InvalidEmailFormat.new(value, schema.object_reference)]
77
80
  end
81
+
82
+ def validate_uuid_format(value, schema)
83
+ return [value, nil] unless schema.format == 'uuid'
84
+
85
+ return [value, nil] if value.match(/[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}/)
86
+
87
+ return [nil, OpenAPIParser::InvalidUUIDFormat.new(value, schema.object_reference)]
88
+ end
78
89
  end
79
90
  end
@@ -5,11 +5,16 @@
5
5
 
6
6
  module OpenAPIParser::Schemas
7
7
  class OpenAPI < Base
8
- def initialize(raw_schema, config)
8
+ def initialize(raw_schema, config, uri: nil, schema_registry: {})
9
9
  super('#', nil, self, raw_schema)
10
10
  @find_object_cache = {}
11
11
  @path_item_finder = OpenAPIParser::PathItemFinder.new(paths) if paths # invalid definition
12
12
  @config = config
13
+ @uri = uri
14
+ @schema_registry = schema_registry
15
+
16
+ # schema_registery is shared among schemas, and prevents a schema from being loaded multiple times
17
+ schema_registry[uri] = self if uri
13
18
  end
14
19
 
15
20
  # @!attribute [r] openapi
@@ -28,5 +33,27 @@ module OpenAPIParser::Schemas
28
33
  def request_operation(http_method, request_path)
29
34
  OpenAPIParser::RequestOperation.create(http_method, request_path, @path_item_finder, @config)
30
35
  end
36
+
37
+ # load another schema with shared config and schema_registry
38
+ # @return [OpenAPIParser::Schemas::OpenAPI]
39
+ def load_another_schema(uri)
40
+ resolved_uri = resolve_uri(uri)
41
+ return if resolved_uri.nil?
42
+
43
+ loaded = @schema_registry[resolved_uri]
44
+ return loaded if loaded
45
+
46
+ OpenAPIParser.load_uri(resolved_uri, config: @config, schema_registry: @schema_registry)
47
+ end
48
+
49
+ private
50
+
51
+ def resolve_uri(uri)
52
+ if uri.absolute?
53
+ uri
54
+ else
55
+ @uri&.merge(uri)
56
+ end
57
+ end
31
58
  end
32
59
  end
@@ -2,6 +2,6 @@ module OpenAPIParser::Schemas
2
2
  class Paths < Base
3
3
  # @!attribute [r] path
4
4
  # @return [Hash{String => PathItem, Reference}, nil]
5
- openapi_attr_hash_body_objects 'path', PathItem, reference: false, allow_data_type: false
5
+ openapi_attr_hash_body_objects 'path', PathItem, reference: true, allow_data_type: false
6
6
  end
7
7
  end
@@ -1,3 +1,3 @@
1
1
  module OpenAPIParser
2
- VERSION = '0.9.0'.freeze
2
+ VERSION = '0.10.0'.freeze
3
3
  end
@@ -24,9 +24,9 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.add_development_dependency 'bundler', '>= 1.16'
26
26
  spec.add_development_dependency 'fincop'
27
- spec.add_development_dependency 'pry'
27
+ spec.add_development_dependency 'pry', '~> 0.12.0'
28
28
  spec.add_development_dependency 'pry-byebug'
29
- spec.add_development_dependency 'rake', '~> 10.0'
29
+ spec.add_development_dependency 'rake', '>= 12.3.3'
30
30
  spec.add_development_dependency 'rspec', '~> 3.0'
31
31
  spec.add_development_dependency 'rspec-parameterized'
32
32
  spec.add_development_dependency 'simplecov'
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.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ota42y
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-03-22 00:00:00.000000000 Z
11
+ date: 2020-04-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -42,16 +42,16 @@ dependencies:
42
42
  name: pry
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: 0.12.0
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: 0.12.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: pry-byebug
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -70,16 +70,16 @@ dependencies:
70
70
  name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: '10.0'
75
+ version: 12.3.3
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: '10.0'
82
+ version: 12.3.3
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rspec
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -222,7 +222,7 @@ 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
225
+ rubygems_version: 3.0.3
226
226
  signing_key:
227
227
  specification_version: 4
228
228
  summary: OpenAPI3 parser