rat_pack_swagger 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|