openapi_parser 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +5 -2
- data/.rubocop_ignore.yml +6 -0
- data/.travis.yml +33 -4
- data/CHANGELOG.md +9 -0
- data/README.md +39 -6
- data/lib/openapi_parser/concern.rb +2 -1
- data/lib/openapi_parser/concerns/expandable.rb +52 -44
- data/lib/openapi_parser/concerns/media_type_selectable.rb +26 -0
- data/lib/openapi_parser/concerns/parser.rb +43 -0
- data/lib/openapi_parser/concerns/parser/core.rb +21 -0
- data/lib/openapi_parser/concerns/parser/hash.rb +10 -0
- data/lib/openapi_parser/concerns/parser/hash_body.rb +12 -0
- data/lib/openapi_parser/concerns/parser/list.rb +10 -0
- data/lib/openapi_parser/concerns/parser/object.rb +14 -0
- data/lib/openapi_parser/concerns/parser/value.rb +14 -0
- data/lib/openapi_parser/concerns/schema_loader.rb +58 -0
- data/lib/openapi_parser/concerns/schema_loader/base.rb +28 -0
- data/lib/openapi_parser/concerns/schema_loader/creator.rb +48 -0
- data/lib/openapi_parser/concerns/schema_loader/hash_body_loader.rb +37 -0
- data/lib/openapi_parser/concerns/schema_loader/hash_objects_loader.rb +29 -0
- data/lib/openapi_parser/concerns/schema_loader/list_loader.rb +28 -0
- data/lib/openapi_parser/concerns/schema_loader/objects_loader.rb +21 -0
- data/lib/openapi_parser/concerns/schema_loader/values_loader.rb +10 -0
- data/lib/openapi_parser/config.rb +1 -1
- data/lib/openapi_parser/errors.rb +9 -0
- data/lib/openapi_parser/path_item_finder.rb +18 -18
- data/lib/openapi_parser/request_operation.rb +4 -4
- data/lib/openapi_parser/schema_validator.rb +77 -54
- data/lib/openapi_parser/schema_validators/all_of_validator.rb +16 -0
- data/lib/openapi_parser/schema_validators/any_of_validator.rb +1 -1
- data/lib/openapi_parser/schema_validators/array_validator.rb +2 -4
- data/lib/openapi_parser/schema_validators/base.rb +9 -6
- data/lib/openapi_parser/schema_validators/boolean_validator.rb +11 -9
- data/lib/openapi_parser/schema_validators/float_validator.rb +8 -10
- data/lib/openapi_parser/schema_validators/integer_validator.rb +11 -10
- data/lib/openapi_parser/schema_validators/nil_validator.rb +1 -0
- data/lib/openapi_parser/schema_validators/object_validator.rb +3 -3
- data/lib/openapi_parser/schema_validators/string_validator.rb +13 -13
- data/lib/openapi_parser/schemas/base.rb +1 -2
- data/lib/openapi_parser/schemas/media_type.rb +3 -1
- data/lib/openapi_parser/schemas/openapi.rb +1 -1
- data/lib/openapi_parser/schemas/operation.rb +17 -14
- data/lib/openapi_parser/schemas/parameter.rb +2 -2
- data/lib/openapi_parser/schemas/request_body.rb +12 -5
- data/lib/openapi_parser/schemas/response.rb +4 -4
- data/lib/openapi_parser/schemas/responses.rb +21 -3
- data/lib/openapi_parser/version.rb +1 -1
- data/openapi_parser.gemspec +3 -2
- metadata +51 -19
- data/lib/openapi_parser/concerns/parseable.rb +0 -238
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0035d4ece30f151226f04a1462ae6cf4d54c36011b315810bd49588f66b0632
|
4
|
+
data.tar.gz: cae26e5b18e0ab71b2027d56a828cccd737126852b96c68facf88f8ba27db0ab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0456ee6d9363ff05c1ef517cbc9aa8cfbcad55aa054e012009ec685a5b97c7779c897842918a868dae3acefa143bbfa7790fc7bb1ba370e04293fc7ead130ef4
|
7
|
+
data.tar.gz: d2855d0574bfdc5a769576ffa89af5d1006f960af4a4790e92edfbe5763eb3a954698f71522d599524b1b9d906f11632440167c4e37e524435804873aeede533
|
data/.rubocop.yml
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
inherit_gem:
|
2
2
|
fincop:
|
3
|
-
- 'config/rails.yml'
|
3
|
+
# - 'config/rails.yml'
|
4
4
|
- 'config/rspec.yml'
|
5
5
|
- 'config/rubocop.yml'
|
6
|
-
|
6
|
+
# If you are using Rails 4, activate this cop.
|
7
7
|
# - 'config/disabled_for_rails_4.yml'
|
8
8
|
|
9
|
+
inherit_from:
|
10
|
+
- '.rubocop_ignore.yml'
|
11
|
+
|
9
12
|
AllCops:
|
10
13
|
TargetRubyVersion: 2.5
|
data/.rubocop_ignore.yml
ADDED
data/.travis.yml
CHANGED
@@ -1,7 +1,36 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
env:
|
2
|
+
global:
|
3
|
+
- CC_TEST_REPORTER_ID=b49a1717b8ff0aef9eced41d0f87d350a88b46d55083ba2e3df8b6f441ae3fb7
|
4
|
+
|
3
5
|
language: ruby
|
4
|
-
|
6
|
+
|
5
7
|
rvm:
|
8
|
+
- 2.3.8
|
9
|
+
- 2.4.5
|
6
10
|
- 2.5.3
|
7
|
-
|
11
|
+
- 2.6.0
|
12
|
+
- ruby-head
|
13
|
+
|
14
|
+
cache: bundler
|
15
|
+
|
16
|
+
before_script:
|
17
|
+
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
18
|
+
- chmod +x ./cc-test-reporter
|
19
|
+
- ./cc-test-reporter before-build
|
20
|
+
|
21
|
+
script: bundle exec rspec
|
22
|
+
|
23
|
+
after_script:
|
24
|
+
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
|
25
|
+
|
26
|
+
notifications:
|
27
|
+
email: false
|
28
|
+
|
29
|
+
sudo: false
|
30
|
+
|
31
|
+
git:
|
32
|
+
depth: 10
|
33
|
+
|
34
|
+
matrix:
|
35
|
+
allow_failures:
|
36
|
+
- rvm: ruby-head
|
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -1,8 +1,41 @@
|
|
1
1
|
# OpenAPI Parser
|
2
|
+
[![Build Status](https://travis-ci.org/ota42y/openapi_parser.svg?branch=master)](https://travis-ci.org/ota42y/openapi_parser)
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/openapi_parser.svg)](https://badge.fury.io/rb/openapi_parser)
|
4
|
+
[![Yard Docs](https://img.shields.io/badge/yard-docs-blue.svg)](https://www.rubydoc.info/gems/openapi_parser)
|
5
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/62bad4bcb3f691d46487/maintainability)](https://codeclimate.com/github/ota42y/openapi_parser/maintainability)
|
6
|
+
[![Test Coverage](https://api.codeclimate.com/v1/badges/62bad4bcb3f691d46487/test_coverage)](https://codeclimate.com/github/ota42y/openapi_parser/test_coverage)
|
7
|
+
[![Inch CI](https://inch-ci.org/github/ota42y/openapi_parser.svg?branch=master)](https://inch-ci.org/github/ota42y/openapi_parser)
|
2
8
|
|
3
|
-
|
9
|
+
This is OpenAPI3 parser and validator.
|
4
10
|
|
5
|
-
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
root = OpenAPIParser.parse(YAML.load_file('open_api_3/schema.yml'))
|
15
|
+
|
16
|
+
# request operation combine path parameters and OpenAPI3's Operation Object
|
17
|
+
request_operation = root.request_operation(:post, '/validate')
|
18
|
+
|
19
|
+
ret = request_operation.validate_request_body('application/json', {"integer" => 1})
|
20
|
+
# => {"integer" => 1}
|
21
|
+
|
22
|
+
# invalid parameter
|
23
|
+
request_operation.validate_request_body('application/json', {"integer" => '1'})
|
24
|
+
# => OpenAPIParser::ValidateError: 1 class is String but it's not valid integer in #/paths/~1validate/post/requestBody/content/application~1json/schema/properties/integer
|
25
|
+
|
26
|
+
# path parameter
|
27
|
+
request_operation = root.request_operation(:get, '/path_template_test/1')
|
28
|
+
request_operation.path_params
|
29
|
+
# => {"template_name"=>"1"}
|
30
|
+
|
31
|
+
# coerce parameter
|
32
|
+
root = OpenAPIParser.parse(YAML.load_file('open_api_3/schema.yml'), {coerce_value: true, datetime_coerce_class: DateTime})
|
33
|
+
request_operation = root.request_operation(:get, '/string_params_coercer')
|
34
|
+
request_operation.validate_request_parameter({'integer_1' => '1', 'datetime_string' => '2016-04-01T16:00:00+09:00'})
|
35
|
+
# => {"integer_1"=>1, "datetime_string"=>#<DateTime: 2016-04-01T16:00:00+09:00 ((2457480j,25200s,0n),+32400s,2299161j)>
|
36
|
+
# convert number string to Integer and datetime string to DateTime class
|
37
|
+
|
38
|
+
```
|
6
39
|
|
7
40
|
## Installation
|
8
41
|
|
@@ -20,9 +53,9 @@ Or install it yourself as:
|
|
20
53
|
|
21
54
|
$ gem install openapi_parser
|
22
55
|
|
23
|
-
##
|
24
|
-
|
25
|
-
|
56
|
+
## ToDo
|
57
|
+
- correct schema checker
|
58
|
+
- more detailed validator
|
26
59
|
|
27
60
|
## Development
|
28
61
|
|
@@ -32,7 +65,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
32
65
|
|
33
66
|
## Contributing
|
34
67
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
68
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/ota42y/openapi_parser. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
36
69
|
|
37
70
|
## License
|
38
71
|
|
@@ -1,25 +1,30 @@
|
|
1
1
|
module OpenAPIParser::Expandable
|
2
|
+
# expand refs
|
3
|
+
# @param [OpenAPIParser::Schemas::Base] root
|
4
|
+
# @return nil
|
2
5
|
def expand_reference(root)
|
3
|
-
expand_list_objects(root, self.class._openapi_attr_list_objects
|
4
|
-
expand_objects(root, self.class._openapi_attr_objects
|
5
|
-
expand_hash_objects(root, self.class._openapi_attr_hash_objects
|
6
|
-
expand_hash_objects(root, self.class._openapi_attr_hash_body_objects
|
6
|
+
expand_list_objects(root, self.class._openapi_attr_list_objects.keys)
|
7
|
+
expand_objects(root, self.class._openapi_attr_objects.keys)
|
8
|
+
expand_hash_objects(root, self.class._openapi_attr_hash_objects.keys)
|
9
|
+
expand_hash_objects(root, self.class._openapi_attr_hash_body_objects.keys)
|
10
|
+
nil
|
7
11
|
end
|
8
12
|
|
9
13
|
private
|
10
14
|
|
11
|
-
|
12
|
-
|
15
|
+
def expand_hash_objects(root, attribute_names)
|
16
|
+
return unless attribute_names
|
13
17
|
|
14
|
-
|
18
|
+
attribute_names.each { |name| expand_hash_attribute(root, name) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def expand_hash_attribute(root, name)
|
15
22
|
h = send(name)
|
16
|
-
|
23
|
+
return if h.nil?
|
17
24
|
|
18
25
|
update_values = h.map do |k, v|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
nil
|
26
|
+
new_object = expand_object(root, v)
|
27
|
+
new_object.nil? ? nil : [k, new_object]
|
23
28
|
end
|
24
29
|
|
25
30
|
update_values.compact.each do |k, v|
|
@@ -27,50 +32,53 @@ module OpenAPIParser::Expandable
|
|
27
32
|
h[k] = v
|
28
33
|
end
|
29
34
|
end
|
30
|
-
end
|
31
35
|
|
32
|
-
|
33
|
-
|
36
|
+
def expand_objects(root, attribute_names)
|
37
|
+
return unless attribute_names
|
34
38
|
|
35
|
-
|
36
|
-
|
37
|
-
|
39
|
+
attribute_names.each do |name|
|
40
|
+
v = send(name)
|
41
|
+
next if v.nil?
|
38
42
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
v.expand_reference(root)
|
43
|
+
new_object = expand_object(root, v)
|
44
|
+
next if new_object.nil?
|
45
|
+
|
46
|
+
_update_child_object(v, new_object)
|
47
|
+
self.instance_variable_set("@#{name}", new_object)
|
45
48
|
end
|
46
49
|
end
|
47
|
-
end
|
48
50
|
|
49
|
-
|
50
|
-
|
51
|
+
def expand_list_objects(root, attribute_names)
|
52
|
+
return unless attribute_names
|
53
|
+
|
54
|
+
attribute_names.each do |name|
|
55
|
+
l = send(name)
|
56
|
+
next if l.nil?
|
51
57
|
|
52
|
-
|
53
|
-
|
54
|
-
|
58
|
+
l.each_with_index do |v, idx|
|
59
|
+
new_object = expand_object(root, v)
|
60
|
+
next if new_object.nil?
|
55
61
|
|
56
|
-
|
57
|
-
|
58
|
-
obj = referenced_object(root, v)
|
59
|
-
_update_child_object(v, obj)
|
60
|
-
l[idx] = obj
|
61
|
-
elsif v.is_a?(OpenAPIParser::Expandable)
|
62
|
-
v.expand_reference(root)
|
62
|
+
_update_child_object(v, new_object)
|
63
|
+
l[idx] = new_object
|
63
64
|
end
|
64
65
|
end
|
65
66
|
end
|
66
|
-
end
|
67
67
|
|
68
|
+
def expand_object(root, object)
|
69
|
+
if object.kind_of?(OpenAPIParser::Schemas::Reference)
|
70
|
+
return referenced_object(root, object)
|
71
|
+
end
|
72
|
+
|
73
|
+
object.expand_reference(root) if object.kind_of?(OpenAPIParser::Expandable)
|
74
|
+
nil
|
75
|
+
end
|
68
76
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
77
|
+
# @param [OpenAPIParser::Schemas::OpenAPI] root
|
78
|
+
# @param [OpenAPIParser::Schemas::Reference] reference
|
79
|
+
def referenced_object(root, reference)
|
80
|
+
obj = root.find_object(reference.ref)
|
73
81
|
|
74
|
-
|
75
|
-
|
82
|
+
obj.kind_of?(OpenAPIParser::Schemas::Reference) ? referenced_object(root, obj) : obj
|
83
|
+
end
|
76
84
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module OpenAPIParser::MediaTypeSelectable
|
2
|
+
# select media type by content_type (consider wild card definition)
|
3
|
+
# @param [String] content_type
|
4
|
+
# @param [Hash{String => OpenAPIParser::Schemas::MediaType}] content
|
5
|
+
# @return [OpenAPIParser::Schemas::MediaType, nil]
|
6
|
+
def select_media_type(content_type, content)
|
7
|
+
return nil unless content_type
|
8
|
+
|
9
|
+
if (media_type = content[content_type])
|
10
|
+
return media_type
|
11
|
+
end
|
12
|
+
|
13
|
+
# application/json => [application, json]
|
14
|
+
splited = content_type.split('/')
|
15
|
+
|
16
|
+
if (media_type = content["#{splited.first}/*"])
|
17
|
+
return media_type
|
18
|
+
end
|
19
|
+
|
20
|
+
if (media_type = content['*/*'])
|
21
|
+
return media_type
|
22
|
+
end
|
23
|
+
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module OpenAPIParser::Parser
|
2
|
+
end
|
3
|
+
|
4
|
+
require_relative './parser/core'
|
5
|
+
require_relative './schema_loader'
|
6
|
+
|
7
|
+
module OpenAPIParser::Parser
|
8
|
+
def self.included(base)
|
9
|
+
base.extend(ClassMethods)
|
10
|
+
end
|
11
|
+
module ClassMethods
|
12
|
+
extend Forwardable
|
13
|
+
|
14
|
+
def_delegators :_parser_core, :_openapi_attr_values, :openapi_attr_value, :openapi_attr_values
|
15
|
+
def_delegators :_parser_core, :_openapi_attr_objects, :openapi_attr_objects, :openapi_attr_object
|
16
|
+
def_delegators :_parser_core, :_openapi_attr_list_objects, :openapi_attr_list_object
|
17
|
+
def_delegators :_parser_core, :_openapi_attr_hash_objects, :openapi_attr_hash_object
|
18
|
+
def_delegators :_parser_core, :_openapi_attr_hash_body_objects, :openapi_attr_hash_body_objects
|
19
|
+
|
20
|
+
def _parser_core
|
21
|
+
@_parser_core ||= OpenAPIParser::Parser::Core.new(self)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param [OpenAPIParser::Schemas::Base] old
|
26
|
+
# @param [OpenAPIParser::Schemas::Base] new
|
27
|
+
def _update_child_object(old, new)
|
28
|
+
_openapi_all_child_objects[old.object_reference] = new
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [Hash{String => OpenAPIParser::Schemas::Base}]
|
32
|
+
def _openapi_all_child_objects
|
33
|
+
@_openapi_all_child_objects ||= {}
|
34
|
+
end
|
35
|
+
|
36
|
+
# load data by schema definition in core and set children to _openapi_all_child_objects
|
37
|
+
# @return nil
|
38
|
+
def load_data
|
39
|
+
loader = ::OpenAPIParser::SchemaLoader.new(self, self.class._parser_core)
|
40
|
+
@_openapi_all_child_objects = loader.load_data
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative './value'
|
2
|
+
require_relative './object'
|
3
|
+
require_relative './list'
|
4
|
+
require_relative './hash'
|
5
|
+
require_relative './hash_body'
|
6
|
+
|
7
|
+
class OpenAPIParser::Parser::Core
|
8
|
+
include OpenAPIParser::Parser::Value
|
9
|
+
include OpenAPIParser::Parser::Object
|
10
|
+
include OpenAPIParser::Parser::List
|
11
|
+
include OpenAPIParser::Parser::Hash
|
12
|
+
include OpenAPIParser::Parser::HashBody
|
13
|
+
|
14
|
+
def initialize(target_klass)
|
15
|
+
@target_klass = target_klass
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
attr_reader :target_klass
|
21
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module OpenAPIParser::Parser::Hash
|
2
|
+
def _openapi_attr_hash_objects
|
3
|
+
@_openapi_attr_hash_objects ||= {}
|
4
|
+
end
|
5
|
+
|
6
|
+
def openapi_attr_hash_object(name, klass, options = {})
|
7
|
+
target_klass.send(:attr_reader, name)
|
8
|
+
_openapi_attr_hash_objects[name] = ::OpenAPIParser::SchemaLoader::HashObjectsLoader.new(name, options.merge(klass: klass))
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module OpenAPIParser::Parser::HashBody
|
2
|
+
def _openapi_attr_hash_body_objects
|
3
|
+
@_openapi_attr_hash_body_objects ||= {}
|
4
|
+
end
|
5
|
+
|
6
|
+
def openapi_attr_hash_body_objects(name, klass, options = {})
|
7
|
+
#options[:reject_keys] = options[:reject_keys] ? options[:reject_keys].map(&:to_s) : []
|
8
|
+
|
9
|
+
target_klass.send(:attr_reader, name)
|
10
|
+
_openapi_attr_hash_body_objects[name] = ::OpenAPIParser::SchemaLoader::HashBodyLoader.new(name, options.merge(klass: klass))
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module OpenAPIParser::Parser::List
|
2
|
+
def _openapi_attr_list_objects
|
3
|
+
@_openapi_attr_list_objects ||= {}
|
4
|
+
end
|
5
|
+
|
6
|
+
def openapi_attr_list_object(name, klass, options = {})
|
7
|
+
target_klass.send(:attr_reader, name)
|
8
|
+
_openapi_attr_list_objects[name] = OpenAPIParser::SchemaLoader::ListLoader.new(name, options.merge(klass: klass))
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module OpenAPIParser::Parser::Object
|
2
|
+
def _openapi_attr_objects
|
3
|
+
@_openapi_attr_objects ||= {}
|
4
|
+
end
|
5
|
+
|
6
|
+
def openapi_attr_objects(*names, klass)
|
7
|
+
names.each { |name| openapi_attr_object(name, klass) }
|
8
|
+
end
|
9
|
+
|
10
|
+
def openapi_attr_object(name, klass, options = {})
|
11
|
+
target_klass.send(:attr_reader, name)
|
12
|
+
_openapi_attr_objects[name] = OpenAPIParser::SchemaLoader::ObjectsLoader.new(name, options.merge(klass: klass))
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module OpenAPIParser::Parser::Value
|
2
|
+
def _openapi_attr_values
|
3
|
+
@_openapi_attr_values ||= {}
|
4
|
+
end
|
5
|
+
|
6
|
+
def openapi_attr_values(*names)
|
7
|
+
names.each { |name| openapi_attr_value(name) }
|
8
|
+
end
|
9
|
+
|
10
|
+
def openapi_attr_value(name, options = {})
|
11
|
+
target_klass.send(:attr_reader, name)
|
12
|
+
_openapi_attr_values[name] = OpenAPIParser::SchemaLoader::ValuesLoader.new(name, options)
|
13
|
+
end
|
14
|
+
end
|