openapi_first 0.21.0 → 1.0.0.beta3
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 +20 -0
- data/Gemfile.lock +14 -25
- data/README.md +31 -185
- data/benchmarks/Gemfile.lock +23 -28
- data/benchmarks/apps/openapi_first_with_hanami_api.ru +1 -2
- data/benchmarks/apps/openapi_first_with_plain_rack.ru +32 -0
- data/benchmarks/apps/openapi_first_with_response_validation.ru +14 -11
- data/benchmarks/apps/openapi_first_with_sinatra.ru +29 -0
- data/examples/app.rb +12 -16
- data/lib/openapi_first/operation.rb +18 -70
- data/lib/openapi_first/request_validation.rb +31 -76
- data/lib/openapi_first/router.rb +9 -5
- data/lib/openapi_first/utils.rb +10 -20
- data/lib/openapi_first/version.rb +1 -1
- data/lib/openapi_first.rb +3 -53
- data/openapi_first.gemspec +2 -3
- metadata +29 -44
- data/benchmarks/apps/openapi_first.ru +0 -22
- data/lib/openapi_first/app.rb +0 -29
- data/lib/openapi_first/coverage.rb +0 -28
- data/lib/openapi_first/default_operation_resolver.rb +0 -63
- data/lib/openapi_first/inbox.rb +0 -13
- data/lib/openapi_first/rack_responder.rb +0 -12
- data/lib/openapi_first/responder.rb +0 -44
- data/lib/openapi_first/response_object.rb +0 -20
- data/lib/openapi_first/validation.rb +0 -15
- /data/benchmarks/apps/{committee.ru → committee_with_hanami_api.ru} +0 -0
data/examples/app.rb
CHANGED
@@ -1,22 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'openapi_first'
|
4
|
+
require 'rack'
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
6
|
+
# This example is a bit contrived, but it shows what you could do with the middlewares
|
7
|
+
|
8
|
+
App = Rack::Builder.new do
|
9
|
+
use OpenapiFirst::RequestValidation, raise_error: true, spec: File.expand_path('./openapi.yaml', __dir__)
|
10
|
+
use OpenapiFirst::ResponseValidation
|
14
11
|
|
15
|
-
|
12
|
+
handlers = {
|
13
|
+
'things#index' => ->(_env) { [200, { 'Content-Type' => 'application/json' }, ['{"hello": "world"}']] }
|
14
|
+
}
|
15
|
+
not_found = ->(_env) { [404, {}, []] }
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
namespace: Web,
|
20
|
-
router_raise_error: OpenapiFirst.env == 'test',
|
21
|
-
response_validation: OpenapiFirst.env == 'test'
|
22
|
-
)
|
17
|
+
run ->(env) { handlers.fetch(env[OpenapiFirst::OPERATION].operation_id, not_found).call(env) }
|
18
|
+
end
|
@@ -4,10 +4,9 @@ require 'forwardable'
|
|
4
4
|
require 'set'
|
5
5
|
require_relative 'schema_validation'
|
6
6
|
require_relative 'utils'
|
7
|
-
require_relative 'response_object'
|
8
7
|
|
9
8
|
module OpenapiFirst
|
10
|
-
class Operation
|
9
|
+
class Operation
|
11
10
|
extend Forwardable
|
12
11
|
def_delegators :operation_object,
|
13
12
|
:[],
|
@@ -40,24 +39,6 @@ module OpenapiFirst
|
|
40
39
|
operation_object['requestBody']
|
41
40
|
end
|
42
41
|
|
43
|
-
def parameters_schema
|
44
|
-
@parameters_schema ||= begin
|
45
|
-
parameters_json_schema = build_parameters_json_schema
|
46
|
-
parameters_json_schema && SchemaValidation.new(parameters_json_schema)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def query_parameters_schema
|
51
|
-
@query_parameters_schema ||= begin
|
52
|
-
query_parameters_json_schema = build_query_parameters_json_schema
|
53
|
-
query_parameters_json_schema && SchemaValidation.new(query_parameters_json_schema)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def content_types_for(status)
|
58
|
-
response_for(status)['content']&.keys
|
59
|
-
end
|
60
|
-
|
61
42
|
def response_schema_for(status, content_type)
|
62
43
|
content = response_for(status)['content']
|
63
44
|
return if content.nil? || content.empty?
|
@@ -102,6 +83,23 @@ module OpenapiFirst
|
|
102
83
|
!!find_content_for_content_type(content, request_content_type)
|
103
84
|
end
|
104
85
|
|
86
|
+
def query_parameters
|
87
|
+
@query_parameters ||= all_parameters.filter { |p| p['in'] == 'query' }
|
88
|
+
end
|
89
|
+
|
90
|
+
def path_parameters
|
91
|
+
@path_parameters ||= all_parameters.filter { |p| p['in'] == 'path' }
|
92
|
+
end
|
93
|
+
|
94
|
+
def all_parameters
|
95
|
+
@all_parameters ||= begin
|
96
|
+
parameters = @path_item_object['parameters']&.dup || []
|
97
|
+
parameters_on_operation = operation_object['parameters']
|
98
|
+
parameters.concat(parameters_on_operation) if parameters_on_operation
|
99
|
+
parameters
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
105
103
|
private
|
106
104
|
|
107
105
|
def response_by_code(status)
|
@@ -121,55 +119,5 @@ module OpenapiFirst
|
|
121
119
|
content[type] || content["#{type.split('/')[0]}/*"] || content['*/*']
|
122
120
|
end
|
123
121
|
end
|
124
|
-
|
125
|
-
def build_parameters_json_schema
|
126
|
-
parameters = all_parameters
|
127
|
-
return unless parameters&.any?
|
128
|
-
|
129
|
-
parameters.each_with_object(new_node) do |parameter, schema|
|
130
|
-
params = Rack::Utils.parse_nested_query(parameter['name'])
|
131
|
-
generate_schema(schema, params, parameter)
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
def build_query_parameters_json_schema
|
136
|
-
query_parameters = all_parameters.reject { |field, _value| field['in'] == 'header' }
|
137
|
-
return unless query_parameters&.any?
|
138
|
-
|
139
|
-
query_parameters.each_with_object(new_node) do |parameter, schema|
|
140
|
-
params = Rack::Utils.parse_nested_query(parameter['name'])
|
141
|
-
generate_schema(schema, params, parameter)
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
def all_parameters
|
146
|
-
parameters = @path_item_object['parameters']&.dup || []
|
147
|
-
parameters_on_operation = operation_object['parameters']
|
148
|
-
parameters.concat(parameters_on_operation) if parameters_on_operation
|
149
|
-
parameters
|
150
|
-
end
|
151
|
-
|
152
|
-
def generate_schema(schema, params, parameter)
|
153
|
-
required = Set.new(schema['required'])
|
154
|
-
params.each do |key, value|
|
155
|
-
required << key if parameter['required']
|
156
|
-
if value.is_a? Hash
|
157
|
-
property_schema = new_node
|
158
|
-
generate_schema(property_schema, value, parameter)
|
159
|
-
Utils.deep_merge!(schema['properties'], { key => property_schema })
|
160
|
-
else
|
161
|
-
schema['properties'][key] = parameter['schema']
|
162
|
-
end
|
163
|
-
end
|
164
|
-
schema['required'] = required.to_a
|
165
|
-
end
|
166
|
-
|
167
|
-
def new_node
|
168
|
-
{
|
169
|
-
'type' => 'object',
|
170
|
-
'required' => [],
|
171
|
-
'properties' => {}
|
172
|
-
}
|
173
|
-
end
|
174
122
|
end
|
175
123
|
end
|
@@ -2,12 +2,12 @@
|
|
2
2
|
|
3
3
|
require 'rack'
|
4
4
|
require 'multi_json'
|
5
|
-
require_relative 'inbox'
|
6
5
|
require_relative 'use_router'
|
7
6
|
require_relative 'validation_format'
|
7
|
+
require 'openapi_parameters'
|
8
8
|
|
9
9
|
module OpenapiFirst
|
10
|
-
class RequestValidation
|
10
|
+
class RequestValidation
|
11
11
|
prepend UseRouter
|
12
12
|
|
13
13
|
def initialize(app, options = {})
|
@@ -19,17 +19,17 @@ module OpenapiFirst
|
|
19
19
|
operation = env[OPERATION]
|
20
20
|
return @app.call(env) unless operation
|
21
21
|
|
22
|
-
env[INBOX] = {}
|
23
22
|
error = catch(:error) do
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
query_params = OpenapiParameters::Query.new(operation.query_parameters).unpack(env['QUERY_STRING'])
|
24
|
+
validate_query_parameters!(operation, query_params)
|
25
|
+
env[PARAMS].merge!(query_params)
|
26
|
+
|
27
27
|
return @app.call(env) unless operation.request_body
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
env[REQUEST_BODY]
|
32
|
-
|
29
|
+
content_type = Rack::Request.new(env).content_type
|
30
|
+
validate_request_content_type!(operation, content_type)
|
31
|
+
parsed_request_body = env[REQUEST_BODY]
|
32
|
+
validate_request_body!(operation, parsed_request_body, content_type)
|
33
33
|
nil
|
34
34
|
end
|
35
35
|
if error
|
@@ -42,23 +42,15 @@ module OpenapiFirst
|
|
42
42
|
|
43
43
|
private
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
def parse_and_validate_request_body!(operation, request)
|
48
|
-
env = request.env
|
49
|
-
|
50
|
-
body = env.delete(ROUTER_PARSED_BODY) if env.key?(ROUTER_PARSED_BODY)
|
51
|
-
|
45
|
+
def validate_request_body!(operation, body, content_type)
|
52
46
|
validate_request_body_presence!(body, operation)
|
53
|
-
return if
|
47
|
+
return if content_type.nil?
|
54
48
|
|
55
|
-
schema = operation&.request_body_schema(
|
49
|
+
schema = operation&.request_body_schema(content_type)
|
56
50
|
return unless schema
|
57
51
|
|
58
52
|
errors = schema.validate(body)
|
59
53
|
throw_error(400, serialize_request_body_errors(errors)) if errors.any?
|
60
|
-
return Utils.deep_symbolize(body) if body.is_a?(Hash)
|
61
|
-
|
62
54
|
body
|
63
55
|
end
|
64
56
|
|
@@ -104,30 +96,29 @@ module OpenapiFirst
|
|
104
96
|
end
|
105
97
|
end
|
106
98
|
|
107
|
-
def
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
99
|
+
def build_json_schema(parameter_defs)
|
100
|
+
init_schema = {
|
101
|
+
'type' => 'object',
|
102
|
+
'properties' => {},
|
103
|
+
'required' => []
|
104
|
+
}
|
105
|
+
parameter_defs.each_with_object(init_schema) do |parameter_def, schema|
|
106
|
+
parameter = OpenapiParameters::Parameter.new(parameter_def)
|
107
|
+
schema['properties'][parameter.name] = parameter.schema if parameter.schema
|
108
|
+
schema['required'] << parameter.name if parameter.required?
|
109
|
+
end
|
116
110
|
end
|
117
111
|
|
118
|
-
def
|
119
|
-
|
120
|
-
|
121
|
-
parameter_name = key_value[0].to_sym
|
122
|
-
schema = key_value[1]
|
123
|
-
next unless params.key?(parameter_name)
|
112
|
+
def validate_query_parameters!(operation, params)
|
113
|
+
parameter_defs = operation.query_parameters
|
114
|
+
return unless parameter_defs&.any?
|
124
115
|
|
125
|
-
|
126
|
-
|
127
|
-
|
116
|
+
json_schema = build_json_schema(parameter_defs)
|
117
|
+
errors = SchemaValidation.new(json_schema).validate(params)
|
118
|
+
throw_error(400, serialize_parameter_errors(errors)) if errors.any?
|
128
119
|
end
|
129
120
|
|
130
|
-
def
|
121
|
+
def serialize_parameter_errors(validation_errors)
|
131
122
|
validation_errors.map do |error|
|
132
123
|
pointer = error['data_pointer'][1..].to_s
|
133
124
|
{
|
@@ -135,41 +126,5 @@ module OpenapiFirst
|
|
135
126
|
}.update(ValidationFormat.error_details(error))
|
136
127
|
end
|
137
128
|
end
|
138
|
-
|
139
|
-
def parse_parameter(value, schema)
|
140
|
-
return filtered_params(schema, value) if schema['properties']
|
141
|
-
|
142
|
-
return parse_array_parameter(value, schema) if schema['type'] == 'array'
|
143
|
-
|
144
|
-
parse_simple_value(value, schema)
|
145
|
-
end
|
146
|
-
|
147
|
-
def parse_array_parameter(value, schema)
|
148
|
-
return value if value.nil? || value.empty?
|
149
|
-
|
150
|
-
array = value.is_a?(Array) ? value : value.split(',')
|
151
|
-
return array unless schema['items']
|
152
|
-
|
153
|
-
array.map! { |e| parse_simple_value(e, schema['items']) }
|
154
|
-
end
|
155
|
-
|
156
|
-
def parse_simple_value(value, schema)
|
157
|
-
return to_boolean(value) if schema['type'] == 'boolean'
|
158
|
-
|
159
|
-
begin
|
160
|
-
return Integer(value, 10) if schema['type'] == 'integer'
|
161
|
-
return Float(value) if schema['type'] == 'number'
|
162
|
-
rescue ArgumentError
|
163
|
-
value
|
164
|
-
end
|
165
|
-
value
|
166
|
-
end
|
167
|
-
|
168
|
-
def to_boolean(value)
|
169
|
-
return true if value == 'true'
|
170
|
-
return false if value == 'false'
|
171
|
-
|
172
|
-
value
|
173
|
-
end
|
174
129
|
end
|
175
130
|
end
|
data/lib/openapi_first/router.rb
CHANGED
@@ -12,7 +12,6 @@ module OpenapiFirst
|
|
12
12
|
options
|
13
13
|
)
|
14
14
|
@app = app
|
15
|
-
@parent_app = options.fetch(:parent_app, nil)
|
16
15
|
@raise = options.fetch(:raise_error, false)
|
17
16
|
@not_found = options.fetch(:not_found, :halt)
|
18
17
|
spec = options.fetch(:spec)
|
@@ -28,8 +27,6 @@ module OpenapiFirst
|
|
28
27
|
env[OPERATION] = nil
|
29
28
|
response = call_router(env)
|
30
29
|
if env[OPERATION].nil?
|
31
|
-
return @parent_app.call(env) if @parent_app # This should only happen if used via OpenapiFirst.middleware
|
32
|
-
|
33
30
|
raise_error(env) if @raise
|
34
31
|
|
35
32
|
return @app.call(env) if @not_found == :continue
|
@@ -39,6 +36,10 @@ module OpenapiFirst
|
|
39
36
|
end
|
40
37
|
|
41
38
|
ORIGINAL_PATH = 'openapi_first.path_info'
|
39
|
+
private_constant :ORIGINAL_PATH
|
40
|
+
|
41
|
+
ROUTER_PARSED_BODY = 'router.parsed_body'
|
42
|
+
private_constant :ROUTER_PARSED_BODY
|
42
43
|
|
43
44
|
private
|
44
45
|
|
@@ -96,8 +97,11 @@ module OpenapiFirst
|
|
96
97
|
def build_route(operation)
|
97
98
|
lambda do |env|
|
98
99
|
env[OPERATION] = operation
|
99
|
-
|
100
|
-
env[
|
100
|
+
path_info = env.delete(ORIGINAL_PATH)
|
101
|
+
env[REQUEST_BODY] = env.delete(ROUTER_PARSED_BODY) if env.key?(ROUTER_PARSED_BODY)
|
102
|
+
route_params = Utils::StringKeyedHash.new(env['router.params'])
|
103
|
+
env[PARAMS] = OpenapiParameters::Path.new(operation.path_parameters).unpack(route_params)
|
104
|
+
env[Rack::PATH_INFO] = path_info
|
101
105
|
@app.call(env)
|
102
106
|
end
|
103
107
|
end
|
data/lib/openapi_first/utils.rb
CHANGED
@@ -1,29 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'hanami/utils/string'
|
4
|
-
require 'hanami/utils/hash'
|
5
|
-
require 'deep_merge/core'
|
6
|
-
|
7
3
|
module OpenapiFirst
|
8
4
|
module Utils
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
def self.underscore(string)
|
14
|
-
Hanami::Utils::String.underscore(string)
|
15
|
-
end
|
5
|
+
class StringKeyedHash
|
6
|
+
def initialize(original)
|
7
|
+
@orig = original
|
8
|
+
end
|
16
9
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
def self.deep_symbolize(hash)
|
22
|
-
Hanami::Utils::Hash.deep_symbolize(hash)
|
23
|
-
end
|
10
|
+
def key?(key)
|
11
|
+
@orig.key?(key.to_sym)
|
12
|
+
end
|
24
13
|
|
25
|
-
|
26
|
-
|
14
|
+
def [](key)
|
15
|
+
@orig[key.to_sym]
|
16
|
+
end
|
27
17
|
end
|
28
18
|
end
|
29
19
|
end
|
data/lib/openapi_first.rb
CHANGED
@@ -5,19 +5,15 @@ require 'json_refs'
|
|
5
5
|
require_relative 'openapi_first/definition'
|
6
6
|
require_relative 'openapi_first/version'
|
7
7
|
require_relative 'openapi_first/errors'
|
8
|
-
require_relative 'openapi_first/inbox'
|
9
8
|
require_relative 'openapi_first/router'
|
10
9
|
require_relative 'openapi_first/request_validation'
|
11
10
|
require_relative 'openapi_first/response_validator'
|
12
11
|
require_relative 'openapi_first/response_validation'
|
13
|
-
require_relative 'openapi_first/responder'
|
14
|
-
require_relative 'openapi_first/app'
|
15
12
|
|
16
13
|
module OpenapiFirst
|
17
|
-
OPERATION = '
|
18
|
-
|
19
|
-
REQUEST_BODY = '
|
20
|
-
INBOX = 'openapi_first.inbox'
|
14
|
+
OPERATION = 'openapi.operation'
|
15
|
+
PARAMS = 'openapi.params'
|
16
|
+
REQUEST_BODY = 'openapi.parsed_request_body'
|
21
17
|
HANDLER = 'openapi_first.handler'
|
22
18
|
|
23
19
|
def self.env
|
@@ -32,50 +28,4 @@ module OpenapiFirst
|
|
32
28
|
resolved['paths'].filter!(&->(key, _) { only.call(key) }) if only
|
33
29
|
Definition.new(resolved, spec_path)
|
34
30
|
end
|
35
|
-
|
36
|
-
def self.app(
|
37
|
-
spec,
|
38
|
-
namespace:,
|
39
|
-
router_raise_error: false,
|
40
|
-
request_validation_raise_error: false,
|
41
|
-
response_validation: false
|
42
|
-
)
|
43
|
-
spec = OpenapiFirst.load(spec) unless spec.is_a?(Definition)
|
44
|
-
App.new(
|
45
|
-
nil,
|
46
|
-
spec,
|
47
|
-
namespace: namespace,
|
48
|
-
router_raise_error: router_raise_error,
|
49
|
-
request_validation_raise_error: request_validation_raise_error,
|
50
|
-
response_validation: response_validation
|
51
|
-
)
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.middleware(
|
55
|
-
spec,
|
56
|
-
namespace:,
|
57
|
-
router_raise_error: false,
|
58
|
-
request_validation_raise_error: false,
|
59
|
-
response_validation: false
|
60
|
-
)
|
61
|
-
spec = OpenapiFirst.load(spec) unless spec.is_a?(Definition)
|
62
|
-
AppWithOptions.new(
|
63
|
-
spec,
|
64
|
-
namespace: namespace,
|
65
|
-
router_raise_error: router_raise_error,
|
66
|
-
request_validation_raise_error: request_validation_raise_error,
|
67
|
-
response_validation: response_validation
|
68
|
-
)
|
69
|
-
end
|
70
|
-
|
71
|
-
class AppWithOptions
|
72
|
-
def initialize(spec, options)
|
73
|
-
@spec = spec
|
74
|
-
@options = options
|
75
|
-
end
|
76
|
-
|
77
|
-
def new(app)
|
78
|
-
App.new(app, @spec, **@options)
|
79
|
-
end
|
80
|
-
end
|
81
31
|
end
|
data/openapi_first.gemspec
CHANGED
@@ -34,13 +34,12 @@ Gem::Specification.new do |spec|
|
|
34
34
|
|
35
35
|
spec.required_ruby_version = '>= 3.0.5'
|
36
36
|
|
37
|
-
spec.add_runtime_dependency 'deep_merge', '>= 1.2.1'
|
38
37
|
spec.add_runtime_dependency 'hanami-router', '~> 2.0.0'
|
39
|
-
spec.add_runtime_dependency 'hanami-utils', '~> 2.0.0'
|
40
38
|
spec.add_runtime_dependency 'json_refs', '~> 0.1', '>= 0.1.7'
|
41
39
|
spec.add_runtime_dependency 'json_schemer', '~> 0.2.16'
|
42
40
|
spec.add_runtime_dependency 'multi_json', '~> 1.14'
|
43
|
-
spec.add_runtime_dependency '
|
41
|
+
spec.add_runtime_dependency 'openapi_parameters', '~> 0.2'
|
42
|
+
spec.add_runtime_dependency 'rack', '>= 2.2', '< 4.0'
|
44
43
|
|
45
44
|
spec.add_development_dependency 'bundler', '~> 2'
|
46
45
|
spec.add_development_dependency 'rack-test', '~> 1'
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openapi_first
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0.beta3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andreas Haller
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-04-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: deep_merge
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 1.2.1
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: 1.2.1
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: hanami-router
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,20 +24,6 @@ dependencies:
|
|
38
24
|
- - "~>"
|
39
25
|
- !ruby/object:Gem::Version
|
40
26
|
version: 2.0.0
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: hanami-utils
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: 2.0.0
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: 2.0.0
|
55
27
|
- !ruby/object:Gem::Dependency
|
56
28
|
name: json_refs
|
57
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -101,19 +73,39 @@ dependencies:
|
|
101
73
|
- !ruby/object:Gem::Version
|
102
74
|
version: '1.14'
|
103
75
|
- !ruby/object:Gem::Dependency
|
104
|
-
name:
|
76
|
+
name: openapi_parameters
|
105
77
|
requirement: !ruby/object:Gem::Requirement
|
106
78
|
requirements:
|
107
79
|
- - "~>"
|
108
80
|
- !ruby/object:Gem::Version
|
109
|
-
version: '
|
81
|
+
version: '0.2'
|
110
82
|
type: :runtime
|
111
83
|
prerelease: false
|
112
84
|
version_requirements: !ruby/object:Gem::Requirement
|
113
85
|
requirements:
|
114
86
|
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0.2'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: rack
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
115
94
|
- !ruby/object:Gem::Version
|
116
95
|
version: '2.2'
|
96
|
+
- - "<"
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '4.0'
|
99
|
+
type: :runtime
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '2.2'
|
106
|
+
- - "<"
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '4.0'
|
117
109
|
- !ruby/object:Gem::Dependency
|
118
110
|
name: bundler
|
119
111
|
requirement: !ruby/object:Gem::Requirement
|
@@ -191,16 +183,17 @@ files:
|
|
191
183
|
- benchmarks/Gemfile
|
192
184
|
- benchmarks/Gemfile.lock
|
193
185
|
- benchmarks/README.md
|
194
|
-
- benchmarks/apps/
|
186
|
+
- benchmarks/apps/committee_with_hanami_api.ru
|
195
187
|
- benchmarks/apps/committee_with_response_validation.ru
|
196
188
|
- benchmarks/apps/committee_with_sinatra.ru
|
197
189
|
- benchmarks/apps/grape.ru
|
198
190
|
- benchmarks/apps/hanami_api.ru
|
199
191
|
- benchmarks/apps/hanami_router.ru
|
200
192
|
- benchmarks/apps/openapi.yaml
|
201
|
-
- benchmarks/apps/openapi_first.ru
|
202
193
|
- benchmarks/apps/openapi_first_with_hanami_api.ru
|
194
|
+
- benchmarks/apps/openapi_first_with_plain_rack.ru
|
203
195
|
- benchmarks/apps/openapi_first_with_response_validation.ru
|
196
|
+
- benchmarks/apps/openapi_first_with_sinatra.ru
|
204
197
|
- benchmarks/apps/roda.ru
|
205
198
|
- benchmarks/apps/sinatra.ru
|
206
199
|
- benchmarks/apps/syro.ru
|
@@ -214,25 +207,17 @@ files:
|
|
214
207
|
- examples/config.ru
|
215
208
|
- examples/openapi.yaml
|
216
209
|
- lib/openapi_first.rb
|
217
|
-
- lib/openapi_first/app.rb
|
218
210
|
- lib/openapi_first/body_parser_middleware.rb
|
219
|
-
- lib/openapi_first/coverage.rb
|
220
|
-
- lib/openapi_first/default_operation_resolver.rb
|
221
211
|
- lib/openapi_first/definition.rb
|
222
212
|
- lib/openapi_first/errors.rb
|
223
|
-
- lib/openapi_first/inbox.rb
|
224
213
|
- lib/openapi_first/operation.rb
|
225
|
-
- lib/openapi_first/rack_responder.rb
|
226
214
|
- lib/openapi_first/request_validation.rb
|
227
|
-
- lib/openapi_first/responder.rb
|
228
|
-
- lib/openapi_first/response_object.rb
|
229
215
|
- lib/openapi_first/response_validation.rb
|
230
216
|
- lib/openapi_first/response_validator.rb
|
231
217
|
- lib/openapi_first/router.rb
|
232
218
|
- lib/openapi_first/schema_validation.rb
|
233
219
|
- lib/openapi_first/use_router.rb
|
234
220
|
- lib/openapi_first/utils.rb
|
235
|
-
- lib/openapi_first/validation.rb
|
236
221
|
- lib/openapi_first/validation_format.rb
|
237
222
|
- lib/openapi_first/version.rb
|
238
223
|
- openapi_first.gemspec
|
@@ -252,9 +237,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
252
237
|
version: 3.0.5
|
253
238
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
254
239
|
requirements:
|
255
|
-
- - "
|
240
|
+
- - ">"
|
256
241
|
- !ruby/object:Gem::Version
|
257
|
-
version:
|
242
|
+
version: 1.3.1
|
258
243
|
requirements: []
|
259
244
|
rubygems_version: 3.3.7
|
260
245
|
signing_key:
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'multi_json'
|
4
|
-
require 'openapi_first'
|
5
|
-
|
6
|
-
namespace = Module.new do
|
7
|
-
def self.find_thing(params, _res)
|
8
|
-
{ hello: 'world', id: params.fetch(:id) }
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.find_things(_params, _res)
|
12
|
-
[{ hello: 'world' }]
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.create_thing(_params, res)
|
16
|
-
res.status = 201
|
17
|
-
{ hello: 'world' }
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
oas_path = File.absolute_path('./openapi.yaml', __dir__)
|
22
|
-
run OpenapiFirst.app(oas_path, namespace: namespace)
|