rat_pack_swagger 0.3.0 → 0.4.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/lib/rat_pack_swagger.rb +59 -205
- data/lib/rat_pack_swagger/version.rb +1 -1
- data/lib/request_validators.rb +40 -0
- data/lib/swagger_json_schema.json +1494 -0
- data/lib/swagger_object.rb +52 -0
- data/lib/swagger_spec.rb +172 -0
- metadata +20 -2
@@ -0,0 +1,52 @@
|
|
1
|
+
class SwaggerObject
|
2
|
+
instance_methods.each do |m|
|
3
|
+
unless m =~ /^__/ || [:inspect, :instance_eval, :object_id].include?(m)
|
4
|
+
undef_method m
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(*args, **kwargs, &block)
|
9
|
+
if args.count > 0 && (!kwargs.empty? || block_given?)
|
10
|
+
raise "Cannot give both unnamed arguments AND named arguments or block to Swagger parameter '#{m}'."
|
11
|
+
elsif block_given?
|
12
|
+
@obj = kwargs unless kwargs.empty?
|
13
|
+
instance_eval &block
|
14
|
+
elsif !kwargs.empty?
|
15
|
+
@obj = kwargs
|
16
|
+
elsif args.count > 0
|
17
|
+
@obj = [*args]
|
18
|
+
else
|
19
|
+
raise "Cannot create SwaggerObject with no arguments."
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def add(*args, **kwargs)
|
24
|
+
@obj ||= []
|
25
|
+
if !@obj.is_a?(Array)
|
26
|
+
raise "Swagger object must be an array to append data '#{item}'"
|
27
|
+
elsif args.count > 0
|
28
|
+
@obj << [*args, kwargs]
|
29
|
+
else
|
30
|
+
@obj << kwargs
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def method_missing(m, *args, **kwargs, &block)
|
35
|
+
@obj ||= {}
|
36
|
+
if block_given?
|
37
|
+
@obj[m] = SwaggerObject.new(**kwargs, &block).to_h
|
38
|
+
elsif !kwargs.empty?
|
39
|
+
@obj[m] = SwaggerObject.new(**kwargs).to_h
|
40
|
+
elsif args.count > 1
|
41
|
+
@obj[m] = [*args]
|
42
|
+
elsif args.count == 1
|
43
|
+
@obj[m] = args[0]
|
44
|
+
else
|
45
|
+
raise "Cannot give zero arguments to Swagger key '#{m}'"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_h
|
50
|
+
@obj
|
51
|
+
end
|
52
|
+
end
|
data/lib/swagger_spec.rb
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module RatPackSwagger
|
4
|
+
module SwaggerType
|
5
|
+
def to_h
|
6
|
+
h = {}
|
7
|
+
getters = methods.select{|m| m =~ /\w+=$/}.map{|m| m.to_s.chop}
|
8
|
+
getters.each do |getter|
|
9
|
+
val = send(getter)
|
10
|
+
next if [nil, [], {}].include?(val)
|
11
|
+
val = val.to_h if val.is_a?(SwaggerType)
|
12
|
+
h[getter.to_sym] = val
|
13
|
+
end
|
14
|
+
return h
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class SwaggerPathItem
|
19
|
+
include SwaggerType
|
20
|
+
attr_accessor :get, :put, :post, :delete, :options, :head, :patch
|
21
|
+
end
|
22
|
+
|
23
|
+
class SwaggerOperation
|
24
|
+
include SwaggerType
|
25
|
+
attr_accessor :tags, :summary, :description,
|
26
|
+
:externalDocs, :consumes, :produces, :parameters, :responses,
|
27
|
+
:schemes, :deprecated, :security
|
28
|
+
def initialize
|
29
|
+
@tags = []
|
30
|
+
@consumes = []
|
31
|
+
@parameters = []
|
32
|
+
@responses = {}
|
33
|
+
@schemes = []
|
34
|
+
@security = []
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class SwaggerSpec
|
39
|
+
attr_accessor :swagger_schema, :spec, :this_route
|
40
|
+
|
41
|
+
def initialize
|
42
|
+
@spec = {
|
43
|
+
paths: {}
|
44
|
+
}
|
45
|
+
@spec_cache_invalid = true
|
46
|
+
@spec_cache = {
|
47
|
+
api_spec: nil, # the data returned byt /v2/swagger.json
|
48
|
+
api_spec_json: nil, # api_spec as json string
|
49
|
+
resolved_spec: nil, # a hash where all json pointers are resolved
|
50
|
+
# for request/response validation, because json-schema sucks at pointers
|
51
|
+
}
|
52
|
+
@swagger_schema = ::JSON.parse(File.read(File.join(File.dirname(__FILE__), 'swagger_json_schema.json')))
|
53
|
+
@this_route = SwaggerOperation.new
|
54
|
+
end
|
55
|
+
|
56
|
+
def route_consumes?(path, verb, mime)
|
57
|
+
route = @spec[:paths][path][verb]
|
58
|
+
return true if route[:consumes] && route[:consumes].include?(mime)
|
59
|
+
return true if @spec[:consumes].include?(mime)
|
60
|
+
return false
|
61
|
+
end
|
62
|
+
|
63
|
+
def register_this_route(path, verb)
|
64
|
+
verb.downcase!
|
65
|
+
paths = @spec[:paths]
|
66
|
+
paths[path] ||= {}
|
67
|
+
paths[path][verb] = @this_route.to_h
|
68
|
+
@this_route = SwaggerOperation.new
|
69
|
+
@spec_cache_invalid = true
|
70
|
+
end
|
71
|
+
|
72
|
+
def add_definitions(*constants)
|
73
|
+
@spec[:definitions] ||= {}
|
74
|
+
constants.each do |constant|
|
75
|
+
if constant.is_a?(Module)
|
76
|
+
constant.constants.each do |c|
|
77
|
+
klass = constant.const_get(c)
|
78
|
+
if klass.is_a?(Class) && klass.ancestors.include?(Definition)
|
79
|
+
@spec[:definitions][c] = klass.definition
|
80
|
+
end
|
81
|
+
end
|
82
|
+
else
|
83
|
+
if constant.is_a?(Class) && constant.ancestors.include?(Definition)
|
84
|
+
@@doc[:definitions][constant.to_s.rpartition('::').last] = constant.definition
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
@spec_cache_invalid = true
|
89
|
+
end
|
90
|
+
|
91
|
+
def resolved_spec
|
92
|
+
update_spec_cache if @spec_cache_invalid
|
93
|
+
@spec_cache[:resolved_spec]
|
94
|
+
end
|
95
|
+
def api_spec
|
96
|
+
update_spec_cache if @spec_cache_invalid
|
97
|
+
@spec_cache[:api_spec]
|
98
|
+
end
|
99
|
+
def api_spec_json
|
100
|
+
update_spec_cache if @spec_cache_invalid
|
101
|
+
@spec_cache[:api_spec_json]
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
def update_spec_cache
|
107
|
+
cache_resolved_spec
|
108
|
+
cache_api_spec
|
109
|
+
@spec_cache[:api_spec_json] = @spec_cache[:api_spec].to_json
|
110
|
+
@spec_cache_invalid = false
|
111
|
+
end
|
112
|
+
|
113
|
+
def cache_resolved_spec
|
114
|
+
resolved_spec = make_deep_copy(@spec)
|
115
|
+
map_hash_values!(resolved_spec) do |k,v|
|
116
|
+
new_v = v
|
117
|
+
if v.is_a?(Hash) && v[:$ref]
|
118
|
+
if v[:$ref].respond_to?(:to_h)
|
119
|
+
new_v = v[:$ref].to_h
|
120
|
+
end
|
121
|
+
end
|
122
|
+
new_v
|
123
|
+
end
|
124
|
+
@spec_cache[:resolved_spec] = resolved_spec
|
125
|
+
end
|
126
|
+
|
127
|
+
def cache_api_spec
|
128
|
+
api_spec = make_deep_copy(@spec)
|
129
|
+
map_hash_values!(api_spec) do |k,v|
|
130
|
+
new_v = v
|
131
|
+
if k.to_s == '$ref'
|
132
|
+
if v.is_a?(Class)
|
133
|
+
classname = v.to_s.rpartition('::').last
|
134
|
+
if v.ancestors.include?(Definition)
|
135
|
+
new_v = "#/definitions/#{classname}"
|
136
|
+
end
|
137
|
+
# TODO: Add other types like Parameters"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
new_v
|
141
|
+
end
|
142
|
+
@spec_cache[:api_spec] = api_spec
|
143
|
+
end
|
144
|
+
|
145
|
+
def make_deep_copy(arg)
|
146
|
+
Marshal.load(Marshal.dump(arg))
|
147
|
+
end
|
148
|
+
|
149
|
+
def map_hash_values!(obj, &block)
|
150
|
+
if obj.is_a? Hash
|
151
|
+
obj.each do |k,v|
|
152
|
+
# perform mapping first, THEN if result is hash/array, go recursive
|
153
|
+
obj[k] = yield(k,v)
|
154
|
+
if obj[k].is_a?(Hash) || obj[k].is_a?(Array)
|
155
|
+
obj[k] = map_hash_values!(obj[k], &block)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
elsif obj.is_a? Array
|
159
|
+
obj.each_with_index do |e,i|
|
160
|
+
if e.is_a?(Hash) || e.is_a?(Array)
|
161
|
+
obj[i] = map_hash_values!(e, &block)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
else
|
165
|
+
raise "Argument must be a Hash or an Array."
|
166
|
+
end
|
167
|
+
return obj
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rat_pack_swagger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Hildebrand
|
@@ -9,8 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-07-
|
12
|
+
date: 2015-07-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: json-schema
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '2.5'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '2.5'
|
14
28
|
- !ruby/object:Gem::Dependency
|
15
29
|
name: sinatra
|
16
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -36,6 +50,10 @@ files:
|
|
36
50
|
- README.md
|
37
51
|
- lib/rat_pack_swagger.rb
|
38
52
|
- lib/rat_pack_swagger/version.rb
|
53
|
+
- lib/request_validators.rb
|
54
|
+
- lib/swagger_json_schema.json
|
55
|
+
- lib/swagger_object.rb
|
56
|
+
- lib/swagger_spec.rb
|
39
57
|
homepage: https://github.com/ckhrysze/rat_pack_swagger
|
40
58
|
licenses:
|
41
59
|
- MIT
|