sinatra-swagger-exposer 0.2.0 → 0.3.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/CHANGELOG.md +4 -0
- data/lib/sinatra/swagger-exposer/configuration/swagger-endpoint-parameter.rb +118 -0
- data/lib/sinatra/swagger-exposer/configuration/swagger-endpoint-response.rb +64 -0
- data/lib/sinatra/swagger-exposer/configuration/swagger-endpoint.rb +88 -0
- data/lib/sinatra/swagger-exposer/configuration/swagger-info.rb +72 -0
- data/lib/sinatra/swagger-exposer/configuration/swagger-parameter-validation-helper.rb +106 -0
- data/lib/sinatra/swagger-exposer/configuration/swagger-type-property.rb +82 -0
- data/lib/sinatra/swagger-exposer/configuration/swagger-type.rb +127 -0
- data/lib/sinatra/swagger-exposer/configuration/swagger-types.rb +51 -0
- data/lib/sinatra/swagger-exposer/processing/swagger-array-value-preprocessor.rb +46 -0
- data/lib/sinatra/swagger-exposer/processing/swagger-base-value-preprocessor.rb +48 -0
- data/lib/sinatra/swagger-exposer/processing/swagger-parameter-preprocessor.rb +47 -0
- data/lib/sinatra/swagger-exposer/processing/swagger-preprocessor-dispatcher.rb +45 -0
- data/lib/sinatra/swagger-exposer/processing/swagger-primitive-value-preprocessor.rb +165 -0
- data/lib/sinatra/swagger-exposer/processing/swagger-request-preprocessor.rb +64 -0
- data/lib/sinatra/swagger-exposer/processing/swagger-type-value-preprocessor.rb +37 -0
- data/lib/sinatra/swagger-exposer/swagger-content-creator.rb +3 -2
- data/lib/sinatra/swagger-exposer/swagger-exposer.rb +18 -20
- data/lib/sinatra/swagger-exposer/swagger-parameter-helper.rb +1 -1
- data/lib/sinatra/swagger-exposer/swagger-preprocessor-creator.rb +137 -0
- data/lib/sinatra/swagger-exposer/swagger-utilities.rb +1 -1
- data/lib/sinatra/swagger-exposer/version.rb +1 -1
- metadata +18 -10
- data/lib/sinatra/swagger-exposer/swagger-endpoint-parameter.rb +0 -197
- data/lib/sinatra/swagger-exposer/swagger-endpoint-response.rb +0 -63
- data/lib/sinatra/swagger-exposer/swagger-endpoint.rb +0 -94
- data/lib/sinatra/swagger-exposer/swagger-info.rb +0 -70
- data/lib/sinatra/swagger-exposer/swagger-parameter-preprocessor.rb +0 -187
- data/lib/sinatra/swagger-exposer/swagger-request-preprocessor.rb +0 -56
- data/lib/sinatra/swagger-exposer/swagger-type-property.rb +0 -72
- data/lib/sinatra/swagger-exposer/swagger-type.rb +0 -125
@@ -1,187 +0,0 @@
|
|
1
|
-
require 'date'
|
2
|
-
|
3
|
-
require_relative 'swagger-endpoint-parameter'
|
4
|
-
require_relative 'swagger-parameter-helper'
|
5
|
-
require_relative 'swagger-invalid-exception'
|
6
|
-
|
7
|
-
module Sinatra
|
8
|
-
|
9
|
-
module SwaggerExposer
|
10
|
-
|
11
|
-
# Process the parameters for validation and enrichment
|
12
|
-
class SwaggerParameterPreprocessor
|
13
|
-
|
14
|
-
include SwaggerParameterHelper
|
15
|
-
|
16
|
-
def initialize(name, how_to_pass, required, type, default, params)
|
17
|
-
@name = name.to_s
|
18
|
-
@how_to_pass = how_to_pass
|
19
|
-
@required = required
|
20
|
-
@type = type
|
21
|
-
@default = default
|
22
|
-
@params = params
|
23
|
-
|
24
|
-
# All headers are upcased
|
25
|
-
if how_to_pass == HOW_TO_PASS_HEADER
|
26
|
-
@name.upcase!
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def useful?
|
31
|
-
@required ||
|
32
|
-
(!@default.nil?) ||
|
33
|
-
[TYPE_NUMBER, TYPE_INTEGER, TYPE_BOOLEAN, TYPE_DATE_TIME].include?(@type) || # Must check type
|
34
|
-
(@params.key? PARAMS_MIN_LENGTH) || (@params.key? PARAMS_MAX_LENGTH) # Must check string
|
35
|
-
end
|
36
|
-
|
37
|
-
def run(app, parsed_body)
|
38
|
-
case @how_to_pass
|
39
|
-
when HOW_TO_PASS_PATH
|
40
|
-
# can't validate
|
41
|
-
when HOW_TO_PASS_QUERY
|
42
|
-
check_param(app.params)
|
43
|
-
when HOW_TO_PASS_HEADER
|
44
|
-
check_param(app.headers)
|
45
|
-
when HOW_TO_PASS_BODY
|
46
|
-
check_param(parsed_body || {})
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def check_param(params)
|
51
|
-
if params.key?(@name)
|
52
|
-
params[@name] = validate_param_value(params[@name])
|
53
|
-
elsif @required
|
54
|
-
raise SwaggerInvalidException.new("Mandatory parameter [#{@name}] is missing")
|
55
|
-
elsif @default
|
56
|
-
params[@name] = @default
|
57
|
-
end
|
58
|
-
params
|
59
|
-
end
|
60
|
-
|
61
|
-
def validate_param_value(value)
|
62
|
-
case @type
|
63
|
-
when TYPE_NUMBER
|
64
|
-
return validate_param_value_number(value)
|
65
|
-
when TYPE_INTEGER
|
66
|
-
return validate_param_value_integer(value)
|
67
|
-
when TYPE_BOOLEAN
|
68
|
-
return validate_param_value_boolean(value)
|
69
|
-
when TYPE_DATE_TIME
|
70
|
-
return validate_param_value_date_time(value)
|
71
|
-
else
|
72
|
-
return validate_param_value_string(value)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
# Validate a boolean parameter
|
77
|
-
def validate_param_value_boolean(value)
|
78
|
-
if (value == 'true') || value.is_a?(TrueClass)
|
79
|
-
return true
|
80
|
-
elsif (value == 'false') || value.is_a?(FalseClass)
|
81
|
-
return false
|
82
|
-
else
|
83
|
-
raise SwaggerInvalidException.new("Parameter [#{@name}] should be an boolean but is [#{value}]")
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
# Validate an integer parameter
|
88
|
-
def validate_param_value_integer(value)
|
89
|
-
begin
|
90
|
-
f = Float(value)
|
91
|
-
i = Integer(value)
|
92
|
-
if f == i
|
93
|
-
i
|
94
|
-
else
|
95
|
-
raise SwaggerInvalidException.new("Parameter [#{@name}] should be an integer but is [#{value}]")
|
96
|
-
end
|
97
|
-
value = Integer(value)
|
98
|
-
validate_numerical_value(value)
|
99
|
-
value
|
100
|
-
rescue ArgumentError
|
101
|
-
raise SwaggerInvalidException.new("Parameter [#{@name}] should be an integer but is [#{value}]")
|
102
|
-
rescue TypeError
|
103
|
-
raise SwaggerInvalidException.new("Parameter [#{@name}] should be an integer but is [#{value}]")
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
# Validate a number parameter
|
108
|
-
def validate_param_value_number(value)
|
109
|
-
begin
|
110
|
-
value = Float(value)
|
111
|
-
validate_numerical_value(value)
|
112
|
-
return value
|
113
|
-
rescue ArgumentError
|
114
|
-
raise SwaggerInvalidException.new("Parameter [#{@name}] should be a float but is [#{value}]")
|
115
|
-
rescue TypeError
|
116
|
-
raise SwaggerInvalidException.new("Parameter [#{@name}] should be a float but is [#{value}]")
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
# Validate a numerical value
|
121
|
-
# @param value [Numeric] the value
|
122
|
-
def validate_numerical_value(value)
|
123
|
-
validate_numerical_value_internal(
|
124
|
-
value,
|
125
|
-
PARAMS_MINIMUM,
|
126
|
-
PARAMS_EXCLUSIVE_MINIMUM,
|
127
|
-
'>=',
|
128
|
-
'>')
|
129
|
-
validate_numerical_value_internal(
|
130
|
-
value,
|
131
|
-
PARAMS_MAXIMUM,
|
132
|
-
PARAMS_EXCLUSIVE_MAXIMUM,
|
133
|
-
'<=',
|
134
|
-
'<')
|
135
|
-
end
|
136
|
-
|
137
|
-
# Validate a date time parameter
|
138
|
-
def validate_param_value_date_time(value)
|
139
|
-
begin
|
140
|
-
DateTime.rfc3339(value)
|
141
|
-
rescue ArgumentError
|
142
|
-
raise SwaggerInvalidException.new("Parameter [#{@name}] should be a date time but is [#{value}]")
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
# Validate a string parameter
|
147
|
-
def validate_param_value_string(value)
|
148
|
-
if value
|
149
|
-
validate_param_value_string_length(value, PARAMS_MIN_LENGTH, '>=')
|
150
|
-
validate_param_value_string_length(value, PARAMS_MAX_LENGTH, '<=')
|
151
|
-
end
|
152
|
-
value
|
153
|
-
end
|
154
|
-
|
155
|
-
# Validate the length of a string parameter
|
156
|
-
# @param value the value to check
|
157
|
-
# @param limit_param_name [Symbol] the param that contain the value to compare to
|
158
|
-
# @param limit_param_method [String] the comparison method to call
|
159
|
-
def validate_param_value_string_length(value, limit_param_name, limit_param_method)
|
160
|
-
if @params.key? limit_param_name
|
161
|
-
target_value = @params[limit_param_name]
|
162
|
-
unless value.length.send(limit_param_method, target_value)
|
163
|
-
raise SwaggerInvalidException.new("Parameter [#{@name}] length should be #{limit_param_method} than #{target_value} but is #{value.length} for [#{value}]")
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
# Validate the value of a number
|
169
|
-
# @param value the value to check
|
170
|
-
# @param limit_param_name [Symbol] the param that contain the value to compare to
|
171
|
-
# @param exclusive_limit_param_name [Symbol] the param that indicates if the comparison is absolute
|
172
|
-
# @param limit_param_method [String] the comparison method to call
|
173
|
-
# @param exclusive_limit_param_method [String] the absolute comparison method to call
|
174
|
-
def validate_numerical_value_internal(value, limit_param_name, exclusive_limit_param_name, limit_param_method, exclusive_limit_param_method)
|
175
|
-
if @params.key? limit_param_name
|
176
|
-
target_value = @params[limit_param_name]
|
177
|
-
method_to_call = @params[exclusive_limit_param_name] ? exclusive_limit_param_method : limit_param_method
|
178
|
-
unless value.send(method_to_call, target_value)
|
179
|
-
raise SwaggerInvalidException.new("Parameter [#{@name}] should be #{method_to_call} than [#{target_value}] but is [#{value}]")
|
180
|
-
end
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
end
|
185
|
-
|
186
|
-
end
|
187
|
-
end
|
@@ -1,56 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
|
3
|
-
require_relative 'swagger-invalid-exception'
|
4
|
-
|
5
|
-
module Sinatra
|
6
|
-
|
7
|
-
module SwaggerExposer
|
8
|
-
|
9
|
-
# A preprocessor for a request, apply the parameter preprocessor then execute the query code
|
10
|
-
class SwaggerRequestPreprocessor
|
11
|
-
|
12
|
-
attr_reader :preprocessors
|
13
|
-
|
14
|
-
def initialize
|
15
|
-
@preprocessors = []
|
16
|
-
end
|
17
|
-
|
18
|
-
def add_preprocessor(preprocessor)
|
19
|
-
@preprocessors << preprocessor
|
20
|
-
end
|
21
|
-
|
22
|
-
# Run the preprocessor the call the route content
|
23
|
-
# @param app the sinatra app being run
|
24
|
-
# @params block_params [Array] the block parameters
|
25
|
-
# @param block the block containing the route content
|
26
|
-
def run(app, block_params, &block)
|
27
|
-
parsed_body = {}
|
28
|
-
if app.env['CONTENT_TYPE'] == 'application/json'
|
29
|
-
body = app.request.body.read
|
30
|
-
unless body.empty?
|
31
|
-
parsed_body = JSON.parse(body)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
app.params['parsed_body'] = parsed_body
|
35
|
-
unless @preprocessors.empty?
|
36
|
-
@preprocessors.each do |preprocessor|
|
37
|
-
begin
|
38
|
-
preprocessor.run(app, parsed_body)
|
39
|
-
rescue SwaggerInvalidException => e
|
40
|
-
app.content_type :json
|
41
|
-
return [400, {:code => 400, :message => e.message}.to_json]
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
if block
|
46
|
-
# Execute the block in the context of the app
|
47
|
-
app.instance_exec(*block_params, &block)
|
48
|
-
else
|
49
|
-
''
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
end
|
@@ -1,72 +0,0 @@
|
|
1
|
-
require_relative 'swagger-utilities'
|
2
|
-
require_relative 'swagger-invalid-exception'
|
3
|
-
|
4
|
-
module Sinatra
|
5
|
-
|
6
|
-
module SwaggerExposer
|
7
|
-
|
8
|
-
# A property of a type
|
9
|
-
class SwaggerTypeProperty
|
10
|
-
|
11
|
-
include SwaggerUtilities
|
12
|
-
|
13
|
-
OTHER_PROPERTIES = [:example, :description, :format, :minLength, :maxLength]
|
14
|
-
PROPERTIES = [:type] + OTHER_PROPERTIES
|
15
|
-
|
16
|
-
def initialize(type_name, property_name, property_properties, known_types)
|
17
|
-
@name = property_name
|
18
|
-
|
19
|
-
unless property_properties.is_a? Hash
|
20
|
-
raise SwaggerInvalidException.new("Property [#{property_name}] value [#{property_properties}] of [#{type_name}] should be a hash")
|
21
|
-
end
|
22
|
-
|
23
|
-
if property_properties.key? :type
|
24
|
-
get_type(property_properties[:type], PRIMITIVE_TYPES + known_types)
|
25
|
-
end
|
26
|
-
|
27
|
-
white_list_params(property_properties, PROPERTIES)
|
28
|
-
|
29
|
-
@other_properties = property_properties.select do |key, value|
|
30
|
-
OTHER_PROPERTIES.include? key
|
31
|
-
end
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
def to_swagger
|
36
|
-
result = @other_properties.clone
|
37
|
-
|
38
|
-
if @type
|
39
|
-
if @type == 'array'
|
40
|
-
result[:type] = 'array'
|
41
|
-
if @items
|
42
|
-
if PRIMITIVE_TYPES.include? @items
|
43
|
-
result[:items] = {:type => @items}
|
44
|
-
else
|
45
|
-
result[:items] = ref_to_type(@items)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
else
|
49
|
-
if PRIMITIVE_TYPES.include? @type
|
50
|
-
result[:type] = @type
|
51
|
-
else
|
52
|
-
result['$ref'] = "#/definitions/#{@type}"
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
result
|
58
|
-
end
|
59
|
-
|
60
|
-
def to_s
|
61
|
-
{
|
62
|
-
:name => @name,
|
63
|
-
:type => @type,
|
64
|
-
:items => @items,
|
65
|
-
:other_properties => @other_properties,
|
66
|
-
}.to_json
|
67
|
-
end
|
68
|
-
|
69
|
-
end
|
70
|
-
|
71
|
-
end
|
72
|
-
end
|
@@ -1,125 +0,0 @@
|
|
1
|
-
require_relative 'swagger-invalid-exception'
|
2
|
-
require_relative 'swagger-type-property'
|
3
|
-
require_relative 'swagger-utilities'
|
4
|
-
|
5
|
-
module Sinatra
|
6
|
-
|
7
|
-
module SwaggerExposer
|
8
|
-
|
9
|
-
# A type
|
10
|
-
class SwaggerType
|
11
|
-
|
12
|
-
include SwaggerUtilities
|
13
|
-
|
14
|
-
PROPERTY_PROPERTIES = :properties
|
15
|
-
PROPERTY_REQUIRED = :required
|
16
|
-
PROPERTY_EXAMPLE = :example
|
17
|
-
PROPERTY_EXTENDS = :extends
|
18
|
-
PROPERTIES = [PROPERTY_PROPERTIES, PROPERTY_REQUIRED, PROPERTY_EXAMPLE, PROPERTY_EXTENDS]
|
19
|
-
|
20
|
-
def initialize(type_name, type_properties, known_types)
|
21
|
-
white_list_params(type_properties, PROPERTIES)
|
22
|
-
@properties = process_properties(type_name, type_properties, known_types)
|
23
|
-
@required = process_required(type_name, type_properties, @properties.keys)
|
24
|
-
@example = process_example(type_name, type_properties, @properties.keys)
|
25
|
-
@extends = process_extends(type_properties, known_types)
|
26
|
-
end
|
27
|
-
|
28
|
-
def process_properties(type_name, type_content, known_types)
|
29
|
-
possible_value = check_attribute_empty_or_bad(type_name, type_content, PROPERTY_PROPERTIES, Hash)
|
30
|
-
if possible_value
|
31
|
-
possible_value
|
32
|
-
else
|
33
|
-
result = {}
|
34
|
-
type_content[PROPERTY_PROPERTIES].each_pair do |property_name, property_properties|
|
35
|
-
result[property_name.to_s] = SwaggerTypeProperty.new(type_name, property_name, property_properties, known_types)
|
36
|
-
end
|
37
|
-
result
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def process_required(type_name, type_content, properties_names)
|
42
|
-
possible_value = check_attribute_empty_or_bad(type_name, type_content, PROPERTY_REQUIRED, Array)
|
43
|
-
if possible_value
|
44
|
-
possible_value
|
45
|
-
else
|
46
|
-
type_content[PROPERTY_REQUIRED].each do |property_name|
|
47
|
-
property_name = property_name.to_s
|
48
|
-
unless properties_names.include? property_name
|
49
|
-
raise SwaggerInvalidException.new("Required property [#{property_name}] of [#{type_name}] is unknown#{list_or_none(properties_names, 'properties')}")
|
50
|
-
end
|
51
|
-
end
|
52
|
-
type_content[PROPERTY_REQUIRED]
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def process_example(type_name, type_content, properties_names)
|
57
|
-
possible_value = check_attribute_empty_or_bad(type_name, type_content, PROPERTY_EXAMPLE, Hash)
|
58
|
-
if possible_value
|
59
|
-
possible_value
|
60
|
-
else
|
61
|
-
type_content[PROPERTY_EXAMPLE].each_pair do |property_name, property_value|
|
62
|
-
property_name = property_name.to_s
|
63
|
-
unless properties_names.include? property_name
|
64
|
-
raise SwaggerInvalidException.new("Example property [#{property_name}] with value [#{property_value}] of [#{type_name}] is unknown#{list_or_none(properties_names, 'properties')}")
|
65
|
-
end
|
66
|
-
end
|
67
|
-
type_content[PROPERTY_EXAMPLE]
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def check_attribute_empty_or_bad(type_name, type_content, attribute_name, attribute_class)
|
72
|
-
if !type_content.key?(attribute_name)
|
73
|
-
attribute_class.new
|
74
|
-
elsif !type_content[attribute_name].is_a? attribute_class
|
75
|
-
raise SwaggerInvalidException.new("Attribute [#{attribute_name}] of #{type_name} is not an hash: #{type_content[attribute_name]}")
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def process_extends(type_properties, known_types)
|
80
|
-
if type_properties.key? PROPERTY_EXTENDS
|
81
|
-
check_type(type_properties[PROPERTY_EXTENDS], known_types)
|
82
|
-
@extends = type_properties[PROPERTY_EXTENDS]
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def to_swagger
|
87
|
-
result = {:type => 'object'}
|
88
|
-
|
89
|
-
unless @properties.empty?
|
90
|
-
result[PROPERTY_PROPERTIES] = hash_to_swagger(@properties)
|
91
|
-
end
|
92
|
-
|
93
|
-
unless @required.empty?
|
94
|
-
result[PROPERTY_REQUIRED] = @required
|
95
|
-
end
|
96
|
-
|
97
|
-
unless @example.empty?
|
98
|
-
result[PROPERTY_EXAMPLE] = @example
|
99
|
-
end
|
100
|
-
|
101
|
-
if @extends
|
102
|
-
result = {
|
103
|
-
:allOf => [
|
104
|
-
ref_to_type(@extends),
|
105
|
-
result
|
106
|
-
]
|
107
|
-
}
|
108
|
-
end
|
109
|
-
|
110
|
-
result
|
111
|
-
end
|
112
|
-
|
113
|
-
def to_s
|
114
|
-
{
|
115
|
-
:properties => @properties,
|
116
|
-
:required => @required,
|
117
|
-
:example => @example,
|
118
|
-
}.to_json
|
119
|
-
end
|
120
|
-
|
121
|
-
|
122
|
-
end
|
123
|
-
|
124
|
-
end
|
125
|
-
end
|