openapi_first 1.0.0.beta5 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +2 -1
- data/CHANGELOG.md +23 -2
- data/Gemfile +2 -0
- data/Gemfile.lock +16 -18
- data/Gemfile.rack2 +15 -0
- data/Gemfile.rack2.lock +99 -0
- data/README.md +99 -130
- data/lib/openapi_first/body_parser.rb +29 -0
- data/lib/openapi_first/configuration.rb +20 -0
- data/lib/openapi_first/definition/cookie_parameters.rb +12 -0
- data/lib/openapi_first/definition/header_parameters.rb +12 -0
- data/lib/openapi_first/definition/operation.rb +116 -0
- data/lib/openapi_first/definition/parameters.rb +47 -0
- data/lib/openapi_first/definition/path_item.rb +32 -0
- data/lib/openapi_first/definition/path_parameters.rb +12 -0
- data/lib/openapi_first/definition/query_parameters.rb +12 -0
- data/lib/openapi_first/definition/request_body.rb +43 -0
- data/lib/openapi_first/definition/response.rb +25 -0
- data/lib/openapi_first/definition/responses.rb +83 -0
- data/lib/openapi_first/definition.rb +61 -8
- data/lib/openapi_first/error_response.rb +22 -27
- data/lib/openapi_first/errors.rb +2 -14
- data/lib/openapi_first/failure.rb +55 -0
- data/lib/openapi_first/middlewares/request_validation.rb +52 -0
- data/lib/openapi_first/middlewares/response_validation.rb +35 -0
- data/lib/openapi_first/plugins/default/error_response.rb +74 -0
- data/lib/openapi_first/plugins/default.rb +11 -0
- data/lib/openapi_first/plugins/jsonapi/error_response.rb +58 -0
- data/lib/openapi_first/plugins/jsonapi.rb +11 -0
- data/lib/openapi_first/plugins.rb +9 -7
- data/lib/openapi_first/request_validation/request_body_validator.rb +41 -0
- data/lib/openapi_first/request_validation/validator.rb +81 -0
- data/lib/openapi_first/response_validation/validator.rb +101 -0
- data/lib/openapi_first/runtime_request.rb +84 -0
- data/lib/openapi_first/runtime_response.rb +31 -0
- data/lib/openapi_first/schema/validation_error.rb +18 -0
- data/lib/openapi_first/schema/validation_result.rb +32 -0
- data/lib/openapi_first/{json_schema.rb → schema.rb} +9 -5
- data/lib/openapi_first/version.rb +1 -1
- data/lib/openapi_first.rb +32 -28
- data/openapi_first.gemspec +10 -9
- metadata +55 -67
- data/.rspec +0 -3
- data/.rubocop.yml +0 -14
- data/Rakefile +0 -15
- data/benchmarks/Gemfile +0 -16
- data/benchmarks/Gemfile.lock +0 -142
- data/benchmarks/README.md +0 -29
- data/benchmarks/apps/committee_with_hanami_api.ru +0 -26
- data/benchmarks/apps/committee_with_response_validation.ru +0 -29
- data/benchmarks/apps/committee_with_sinatra.ru +0 -31
- data/benchmarks/apps/grape.ru +0 -21
- data/benchmarks/apps/hanami_api.ru +0 -21
- data/benchmarks/apps/hanami_router.ru +0 -14
- data/benchmarks/apps/openapi.yaml +0 -268
- data/benchmarks/apps/openapi_first_with_hanami_api.ru +0 -24
- data/benchmarks/apps/openapi_first_with_plain_rack.ru +0 -32
- data/benchmarks/apps/openapi_first_with_response_validation.ru +0 -25
- data/benchmarks/apps/openapi_first_with_sinatra.ru +0 -29
- data/benchmarks/apps/roda.ru +0 -27
- data/benchmarks/apps/sinatra.ru +0 -26
- data/benchmarks/apps/syro.ru +0 -25
- data/benchmarks/benchmark-wrk.sh +0 -3
- data/benchmarks/benchmarks.rb +0 -48
- data/benchmarks/post.lua +0 -3
- data/bin/console +0 -15
- data/bin/setup +0 -8
- data/examples/README.md +0 -13
- data/examples/app.rb +0 -18
- data/examples/config.ru +0 -7
- data/examples/openapi.yaml +0 -29
- data/lib/openapi_first/body_parser_middleware.rb +0 -40
- data/lib/openapi_first/config.rb +0 -20
- data/lib/openapi_first/error_responses/default.rb +0 -58
- data/lib/openapi_first/error_responses/json_api.rb +0 -58
- data/lib/openapi_first/json_schema/result.rb +0 -17
- data/lib/openapi_first/operation.rb +0 -170
- data/lib/openapi_first/request_body_validator.rb +0 -41
- data/lib/openapi_first/request_validation.rb +0 -118
- data/lib/openapi_first/request_validation_error.rb +0 -31
- data/lib/openapi_first/response_validation.rb +0 -93
- data/lib/openapi_first/response_validator.rb +0 -21
- data/lib/openapi_first/router.rb +0 -102
- data/lib/openapi_first/string_keyed_hash.rb +0 -20
- data/lib/openapi_first/use_router.rb +0 -18
data/lib/openapi_first/router.rb
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'rack'
|
4
|
-
require 'multi_json'
|
5
|
-
require 'hanami/router'
|
6
|
-
require_relative 'body_parser_middleware'
|
7
|
-
|
8
|
-
module OpenapiFirst
|
9
|
-
class Router
|
10
|
-
# The unconverted path parameters before they are converted to the types defined in the API description
|
11
|
-
RAW_PATH_PARAMS = 'openapi.raw_path_params'
|
12
|
-
|
13
|
-
def initialize(
|
14
|
-
app,
|
15
|
-
options
|
16
|
-
)
|
17
|
-
@app = app
|
18
|
-
@raise = options.fetch(:raise_error, false)
|
19
|
-
@not_found = options.fetch(:not_found, :halt)
|
20
|
-
@error_response_class = options.fetch(:error_response, Config.default_options.error_response)
|
21
|
-
spec = options.fetch(:spec)
|
22
|
-
raise "You have to pass spec: when initializing #{self.class}" unless spec
|
23
|
-
|
24
|
-
spec = OpenapiFirst.load(spec) unless spec.is_a?(Definition)
|
25
|
-
|
26
|
-
@filepath = spec.filepath
|
27
|
-
@router = build_router(spec.operations)
|
28
|
-
end
|
29
|
-
|
30
|
-
def call(env)
|
31
|
-
env[OPERATION] = nil
|
32
|
-
response = call_router(env)
|
33
|
-
if env[OPERATION].nil?
|
34
|
-
raise_error(env) if @raise
|
35
|
-
|
36
|
-
return @app.call(env) if @not_found == :continue
|
37
|
-
end
|
38
|
-
|
39
|
-
response
|
40
|
-
end
|
41
|
-
|
42
|
-
ORIGINAL_PATH = 'openapi_first.path_info'
|
43
|
-
private_constant :ORIGINAL_PATH
|
44
|
-
|
45
|
-
ROUTER_PARSED_BODY = 'router.parsed_body'
|
46
|
-
private_constant :ROUTER_PARSED_BODY
|
47
|
-
|
48
|
-
private
|
49
|
-
|
50
|
-
def raise_error(env)
|
51
|
-
req = Rack::Request.new(env)
|
52
|
-
msg =
|
53
|
-
"Could not find definition for #{req.request_method} '#{
|
54
|
-
req.path
|
55
|
-
}' in API description #{@filepath}"
|
56
|
-
raise NotFoundError, msg
|
57
|
-
end
|
58
|
-
|
59
|
-
def call_router(env)
|
60
|
-
# Changing and restoring PATH_INFO is needed, because Hanami::Router does not respect existing script_path
|
61
|
-
env[ORIGINAL_PATH] = env[Rack::PATH_INFO]
|
62
|
-
env[Rack::PATH_INFO] = Rack::Request.new(env).path
|
63
|
-
@router.call(env)
|
64
|
-
rescue BodyParsingError => e
|
65
|
-
message = e.message
|
66
|
-
raise RequestInvalidError, message if @raise
|
67
|
-
|
68
|
-
error = RequestValidationError.new(status: 400, location: :body, message:)
|
69
|
-
@error_response_class.new(env, error).render
|
70
|
-
ensure
|
71
|
-
env[Rack::PATH_INFO] = env.delete(ORIGINAL_PATH) if env[ORIGINAL_PATH]
|
72
|
-
end
|
73
|
-
|
74
|
-
def build_router(operations)
|
75
|
-
router = Hanami::Router.new.tap do |r|
|
76
|
-
operations.each do |operation|
|
77
|
-
normalized_path = operation.path.gsub('{', ':').gsub('}', '')
|
78
|
-
r.public_send(
|
79
|
-
operation.method,
|
80
|
-
normalized_path,
|
81
|
-
to: build_route(operation)
|
82
|
-
)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
Rack::Builder.app do
|
86
|
-
use(BodyParserMiddleware)
|
87
|
-
run router
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
def build_route(operation)
|
92
|
-
lambda do |env|
|
93
|
-
env[OPERATION] = operation
|
94
|
-
path_info = env.delete(ORIGINAL_PATH)
|
95
|
-
env[REQUEST_BODY] = env.delete(ROUTER_PARSED_BODY) if env.key?(ROUTER_PARSED_BODY)
|
96
|
-
env[RAW_PATH_PARAMS] = env['router.params']
|
97
|
-
env[Rack::PATH_INFO] = path_info
|
98
|
-
@app.call(env)
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module OpenapiFirst
|
4
|
-
class StringKeyedHash
|
5
|
-
extend Forwardable
|
6
|
-
def_delegators :@orig, :empty?
|
7
|
-
|
8
|
-
def initialize(original)
|
9
|
-
@orig = original
|
10
|
-
end
|
11
|
-
|
12
|
-
def key?(key)
|
13
|
-
@orig.key?(key.to_sym)
|
14
|
-
end
|
15
|
-
|
16
|
-
def [](key)
|
17
|
-
@orig[key.to_sym]
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module OpenapiFirst
|
4
|
-
module UseRouter
|
5
|
-
def initialize(app, options = {})
|
6
|
-
@app = app
|
7
|
-
@options = options
|
8
|
-
super
|
9
|
-
end
|
10
|
-
|
11
|
-
def call(env)
|
12
|
-
return super if env.key?(OPERATION)
|
13
|
-
|
14
|
-
@router ||= Router.new(->(e) { super(e) }, @options)
|
15
|
-
@router.call(env)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|