openapi_first 1.0.0.beta6 → 1.0.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 +16 -3
- data/Gemfile +1 -0
- data/Gemfile.lock +11 -10
- data/Gemfile.rack2.lock +99 -0
- data/README.md +99 -130
- data/lib/openapi_first/body_parser.rb +5 -4
- data/lib/openapi_first/configuration.rb +20 -0
- data/lib/openapi_first/definition/operation.rb +84 -71
- data/lib/openapi_first/definition/parameters.rb +1 -1
- data/lib/openapi_first/definition/path_item.rb +21 -12
- data/lib/openapi_first/definition/path_parameters.rb +2 -3
- data/lib/openapi_first/definition/request_body.rb +22 -11
- data/lib/openapi_first/definition/response.rb +19 -31
- data/lib/openapi_first/definition/responses.rb +83 -0
- data/lib/openapi_first/definition.rb +50 -17
- data/lib/openapi_first/error_response.rb +22 -29
- 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/{definition/schema.rb → schema.rb} +8 -4
- data/lib/openapi_first/version.rb +1 -1
- data/lib/openapi_first.rb +32 -28
- data/openapi_first.gemspec +3 -5
- metadata +28 -20
- data/lib/openapi_first/config.rb +0 -20
- data/lib/openapi_first/definition/has_content.rb +0 -37
- data/lib/openapi_first/definition/schema/result.rb +0 -17
- 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/request_body_validator.rb +0 -37
- data/lib/openapi_first/request_validation.rb +0 -122
- data/lib/openapi_first/request_validation_error.rb +0 -31
- data/lib/openapi_first/response_validation.rb +0 -113
- data/lib/openapi_first/response_validator.rb +0 -21
- data/lib/openapi_first/router.rb +0 -68
- data/lib/openapi_first/use_router.rb +0 -18
@@ -3,100 +3,113 @@
|
|
3
3
|
require 'forwardable'
|
4
4
|
require 'set'
|
5
5
|
require_relative 'request_body'
|
6
|
-
require_relative 'response'
|
7
6
|
require_relative 'query_parameters'
|
8
7
|
require_relative 'header_parameters'
|
9
8
|
require_relative 'path_parameters'
|
10
9
|
require_relative 'cookie_parameters'
|
11
|
-
require_relative '
|
10
|
+
require_relative 'responses'
|
12
11
|
|
13
12
|
module OpenapiFirst
|
14
|
-
class
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
13
|
+
class Definition
|
14
|
+
class Operation
|
15
|
+
extend Forwardable
|
16
|
+
def_delegators :operation_object,
|
17
|
+
:[],
|
18
|
+
:dig
|
19
|
+
|
20
|
+
WRITE_METHODS = Set.new(%w[post put patch delete]).freeze
|
21
|
+
private_constant :WRITE_METHODS
|
22
|
+
|
23
|
+
attr_reader :path, :method, :openapi_version
|
24
|
+
|
25
|
+
def initialize(path, request_method, path_item_object, openapi_version:)
|
26
|
+
@path = path
|
27
|
+
@method = request_method
|
28
|
+
@path_item_object = path_item_object
|
29
|
+
@openapi_version = openapi_version
|
30
|
+
@operation_object = @path_item_object[request_method]
|
31
|
+
end
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
def operation_id
|
34
|
+
operation_object['operationId']
|
35
|
+
end
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
def read?
|
38
|
+
!write?
|
39
|
+
end
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
def write?
|
42
|
+
WRITE_METHODS.include?(method)
|
43
|
+
end
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
45
|
+
def request_body
|
46
|
+
@request_body ||= RequestBody.new(operation_object['requestBody'], self) if operation_object['requestBody']
|
47
|
+
end
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
operation_object.dig('responses', "#{status / 100}xx") ||
|
53
|
-
operation_object.dig('responses', 'default')
|
54
|
-
Response.new(status, response_object, self) if response_object
|
55
|
-
end
|
49
|
+
def response_status_defined?(status)
|
50
|
+
responses.status_defined?(status)
|
51
|
+
end
|
56
52
|
|
57
|
-
|
58
|
-
@name ||= "#{method.upcase} #{path} (#{operation_id})"
|
59
|
-
end
|
53
|
+
def_delegators :responses, :response_for
|
60
54
|
|
61
|
-
|
62
|
-
|
63
|
-
|
55
|
+
def schema_for(content_type)
|
56
|
+
content = @request_body_object['content']
|
57
|
+
return unless content&.any?
|
64
58
|
|
65
|
-
|
66
|
-
|
67
|
-
|
59
|
+
content_schemas&.fetch(content_type) do
|
60
|
+
type = content_type.split(';')[0]
|
61
|
+
content_schemas[type] || content_schemas["#{type.split('/')[0]}/*"] || content_schemas['*/*']
|
62
|
+
end
|
63
|
+
end
|
68
64
|
|
69
|
-
|
70
|
-
|
65
|
+
def name
|
66
|
+
@name ||= "#{method.upcase} #{path} (#{operation_id})"
|
67
|
+
end
|
71
68
|
|
72
|
-
|
73
|
-
|
74
|
-
|
69
|
+
def query_parameters
|
70
|
+
@query_parameters ||= build_parameters(all_parameters.filter { |p| p['in'] == 'query' }, QueryParameters)
|
71
|
+
end
|
75
72
|
|
76
|
-
|
77
|
-
|
78
|
-
|
73
|
+
def path_parameters
|
74
|
+
@path_parameters ||= build_parameters(all_parameters.filter { |p| p['in'] == 'path' }, PathParameters)
|
75
|
+
end
|
76
|
+
|
77
|
+
IGNORED_HEADERS = Set['Content-Type', 'Accept', 'Authorization'].freeze
|
78
|
+
private_constant :IGNORED_HEADERS
|
79
79
|
|
80
|
-
|
81
|
-
|
82
|
-
parameters = @path_item_object['parameters']&.dup || []
|
83
|
-
parameters_on_operation = operation_object['parameters']
|
84
|
-
parameters.concat(parameters_on_operation) if parameters_on_operation
|
85
|
-
parameters
|
80
|
+
def header_parameters
|
81
|
+
@header_parameters ||= build_parameters(find_header_parameters, HeaderParameters)
|
86
82
|
end
|
87
|
-
end
|
88
83
|
|
89
|
-
|
84
|
+
def cookie_parameters
|
85
|
+
@cookie_parameters ||= build_parameters(all_parameters.filter { |p| p['in'] == 'cookie' }, CookieParameters)
|
86
|
+
end
|
90
87
|
|
91
|
-
|
88
|
+
private
|
92
89
|
|
93
|
-
|
94
|
-
|
95
|
-
|
90
|
+
def all_parameters
|
91
|
+
@all_parameters ||= begin
|
92
|
+
parameters = @path_item_object['parameters']&.dup || []
|
93
|
+
parameters_on_operation = operation_object['parameters']
|
94
|
+
parameters.concat(parameters_on_operation) if parameters_on_operation
|
95
|
+
parameters
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def responses
|
100
|
+
@responses ||= Responses.new(self, operation_object['responses'])
|
101
|
+
end
|
102
|
+
|
103
|
+
attr_reader :operation_object
|
104
|
+
|
105
|
+
def build_parameters(parameters, klass)
|
106
|
+
klass.new(parameters, openapi_version:) if parameters.any?
|
107
|
+
end
|
96
108
|
|
97
|
-
|
98
|
-
|
99
|
-
|
109
|
+
def find_header_parameters
|
110
|
+
all_parameters.filter do |p|
|
111
|
+
p['in'] == 'header' && !IGNORED_HEADERS.include?(p['name'])
|
112
|
+
end
|
100
113
|
end
|
101
114
|
end
|
102
115
|
end
|
@@ -3,21 +3,30 @@
|
|
3
3
|
require_relative 'operation'
|
4
4
|
|
5
5
|
module OpenapiFirst
|
6
|
-
class
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
class Definition
|
7
|
+
class PathItem
|
8
|
+
def initialize(path, path_item_object, openapi_version:)
|
9
|
+
@path = path
|
10
|
+
@path_item_object = path_item_object
|
11
|
+
@openapi_version = openapi_version
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :path
|
15
|
+
|
16
|
+
def operation(request_method)
|
17
|
+
return unless @path_item_object[request_method]
|
12
18
|
|
13
|
-
|
19
|
+
Operation.new(
|
20
|
+
@path, request_method, @path_item_object, openapi_version: @openapi_version
|
21
|
+
)
|
22
|
+
end
|
14
23
|
|
15
|
-
|
16
|
-
|
24
|
+
METHODS = %w[get head post put patch delete trace options].freeze
|
25
|
+
private_constant :METHODS
|
17
26
|
|
18
|
-
|
19
|
-
@
|
20
|
-
|
27
|
+
def operations
|
28
|
+
@operations ||= @path_item_object.slice(*METHODS).keys.map { |method| operation(method) }
|
29
|
+
end
|
21
30
|
end
|
22
31
|
end
|
23
32
|
end
|
@@ -2,12 +2,11 @@
|
|
2
2
|
|
3
3
|
require 'openapi_parameters'
|
4
4
|
require_relative 'parameters'
|
5
|
-
require_relative '../router'
|
6
5
|
|
7
6
|
module OpenapiFirst
|
8
7
|
class PathParameters < Parameters
|
9
|
-
def unpack(
|
10
|
-
OpenapiParameters::Path.new(@parameter_definitions).unpack(
|
8
|
+
def unpack(original_path_params)
|
9
|
+
OpenapiParameters::Path.new(@parameter_definitions).unpack(original_path_params)
|
11
10
|
end
|
12
11
|
end
|
13
12
|
end
|
@@ -1,32 +1,43 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '
|
3
|
+
require_relative '../schema'
|
4
4
|
|
5
5
|
module OpenapiFirst
|
6
6
|
class RequestBody
|
7
|
-
include HasContent
|
8
|
-
|
9
7
|
def initialize(request_body_object, operation)
|
10
|
-
@
|
8
|
+
@request_body_object = request_body_object
|
11
9
|
@operation = operation
|
12
10
|
end
|
13
11
|
|
14
12
|
def description
|
15
|
-
@
|
13
|
+
@request_body_object['description']
|
16
14
|
end
|
17
15
|
|
18
16
|
def required?
|
19
|
-
!!@
|
17
|
+
!!@request_body_object['required']
|
20
18
|
end
|
21
19
|
|
22
|
-
|
20
|
+
def schema_for(content_type)
|
21
|
+
content = @request_body_object['content']
|
22
|
+
return unless content&.any?
|
23
23
|
|
24
|
-
|
25
|
-
|
24
|
+
content_schemas&.fetch(content_type) do
|
25
|
+
type = content_type.split(';')[0]
|
26
|
+
content_schemas[type] || content_schemas["#{type.split('/')[0]}/*"] || content_schemas['*/*']
|
27
|
+
end
|
26
28
|
end
|
27
29
|
|
28
|
-
|
29
|
-
|
30
|
+
private
|
31
|
+
|
32
|
+
def content_schemas
|
33
|
+
@content_schemas ||= @request_body_object['content']&.each_with_object({}) do |kv, result|
|
34
|
+
type, media_type = kv
|
35
|
+
schema_object = media_type['schema']
|
36
|
+
next unless schema_object
|
37
|
+
|
38
|
+
result[type] = Schema.new(schema_object, write: @operation.write?,
|
39
|
+
openapi_version: @operation.openapi_version)
|
40
|
+
end
|
30
41
|
end
|
31
42
|
end
|
32
43
|
end
|
@@ -1,37 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'has_content'
|
4
|
-
|
5
3
|
module OpenapiFirst
|
6
|
-
class
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
def content?
|
26
|
-
!!content&.any?
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def schema_write? = false
|
32
|
-
|
33
|
-
def content
|
34
|
-
@object['content']
|
4
|
+
class Definition
|
5
|
+
class Response
|
6
|
+
def initialize(operation:, status:, response_object:, content_type:, content_schema:)
|
7
|
+
@operation = operation
|
8
|
+
@response_object = response_object
|
9
|
+
@status = status
|
10
|
+
@content_type = content_type
|
11
|
+
@content_schema = content_schema
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :operation, :status, :content_type, :content_schema
|
15
|
+
|
16
|
+
def headers
|
17
|
+
@response_object['headers']
|
18
|
+
end
|
19
|
+
|
20
|
+
def description
|
21
|
+
@response_object['description']
|
22
|
+
end
|
35
23
|
end
|
36
24
|
end
|
37
25
|
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'response'
|
4
|
+
|
5
|
+
module OpenapiFirst
|
6
|
+
class Definition
|
7
|
+
# @visibility private
|
8
|
+
class Responses
|
9
|
+
def initialize(operation, responses_object)
|
10
|
+
@operation = operation
|
11
|
+
@responses_object = responses_object
|
12
|
+
end
|
13
|
+
|
14
|
+
def status_defined?(status)
|
15
|
+
!!find_response_object(status)
|
16
|
+
end
|
17
|
+
|
18
|
+
def response_for(status, response_content_type)
|
19
|
+
response_object = find_response_object(status)
|
20
|
+
return unless response_object
|
21
|
+
return response_without_content(status, response_object) unless content_defined?(response_object)
|
22
|
+
|
23
|
+
defined_content_type = find_defined_content_type(response_object, response_content_type)
|
24
|
+
return unless defined_content_type
|
25
|
+
|
26
|
+
content_schema = find_content_schema(response_object, response_content_type)
|
27
|
+
Response.new(operation:, status:, response_object:, content_type: defined_content_type, content_schema:)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_reader :openapi_version, :operation
|
33
|
+
|
34
|
+
def response_without_content(status, response_object)
|
35
|
+
Response.new(operation:, status:, response_object:, content_type: nil, content_schema: nil)
|
36
|
+
end
|
37
|
+
|
38
|
+
def find_defined_content_type(response_object, content_type)
|
39
|
+
return if content_type.nil?
|
40
|
+
|
41
|
+
content = response_object['content']
|
42
|
+
return content_type if content.key?(content_type)
|
43
|
+
|
44
|
+
type = content_type.split(';')[0]
|
45
|
+
return type if content.key?(type)
|
46
|
+
|
47
|
+
key = "#{type.split('/')[0]}/*"
|
48
|
+
return key if content.key?(key)
|
49
|
+
|
50
|
+
key = '*/*'
|
51
|
+
key if content.key?(key)
|
52
|
+
end
|
53
|
+
|
54
|
+
def content_defined?(response_object)
|
55
|
+
response_object['content']&.any?
|
56
|
+
end
|
57
|
+
|
58
|
+
def find_content_schema(response_object, response_content_type)
|
59
|
+
return unless response_content_type
|
60
|
+
|
61
|
+
content_object = find_response_body(response_object['content'], response_content_type)
|
62
|
+
content_schema_object = content_object&.fetch('schema', nil)
|
63
|
+
return unless content_schema_object
|
64
|
+
|
65
|
+
Schema.new(content_schema_object, write: false, openapi_version: operation.openapi_version)
|
66
|
+
end
|
67
|
+
|
68
|
+
def find_response_object(status)
|
69
|
+
@responses_object[status.to_s] ||
|
70
|
+
@responses_object["#{status / 100}XX"] ||
|
71
|
+
@responses_object["#{status / 100}xx"] ||
|
72
|
+
@responses_object['default']
|
73
|
+
end
|
74
|
+
|
75
|
+
def find_response_body(content, content_type)
|
76
|
+
content&.fetch(content_type) do |_|
|
77
|
+
type = content_type.split(';')[0]
|
78
|
+
content[type] || content["#{type.split('/')[0]}/*"] || content['*/*']
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'mustermann/template'
|
4
4
|
require_relative 'definition/path_item'
|
5
|
+
require_relative 'runtime_request'
|
5
6
|
|
6
7
|
module OpenapiFirst
|
7
8
|
# Represents an OpenAPI API Description document
|
@@ -14,31 +15,63 @@ module OpenapiFirst
|
|
14
15
|
@openapi_version = detect_version(resolved)
|
15
16
|
end
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
18
|
+
def request(rack_request)
|
19
|
+
path_item, path_params = find_path_item_and_params(rack_request.path)
|
20
|
+
operation = path_item&.operation(rack_request.request_method.downcase)
|
21
|
+
RuntimeRequest.new(
|
22
|
+
request: rack_request,
|
23
|
+
path_item:,
|
24
|
+
operation:,
|
25
|
+
path_params:
|
26
|
+
)
|
27
|
+
end
|
24
28
|
|
25
|
-
|
26
|
-
|
27
|
-
end
|
28
|
-
# Thanks to open ota42y/openapi_parser for this part
|
29
|
-
matches.min_by { |match| match[1].size }
|
29
|
+
def response(rack_request, rack_response)
|
30
|
+
request(rack_request).response(rack_response)
|
30
31
|
end
|
31
32
|
|
32
33
|
def operations
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
@operations ||= path_items.flat_map(&:operations)
|
35
|
+
end
|
36
|
+
|
37
|
+
def path(pathname)
|
38
|
+
return unless paths.key?(pathname)
|
39
|
+
|
40
|
+
PathItem.new(pathname, paths[pathname], openapi_version:)
|
38
41
|
end
|
39
42
|
|
40
43
|
private
|
41
44
|
|
45
|
+
def path_items
|
46
|
+
@path_items ||= paths.flat_map do |path, path_item_object|
|
47
|
+
PathItem.new(path, path_item_object, openapi_version:)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def find_path_item_and_params(request_path)
|
52
|
+
if paths.key?(request_path)
|
53
|
+
return [
|
54
|
+
PathItem.new(request_path, paths[request_path], openapi_version:),
|
55
|
+
{}
|
56
|
+
]
|
57
|
+
end
|
58
|
+
search_for_path_item(request_path)
|
59
|
+
end
|
60
|
+
|
61
|
+
def search_for_path_item(request_path)
|
62
|
+
paths.find do |path, path_item_object|
|
63
|
+
template = Mustermann::Template.new(path)
|
64
|
+
path_params = template.params(request_path)
|
65
|
+
next unless path_params
|
66
|
+
next unless path_params.size == template.names.size
|
67
|
+
|
68
|
+
return [
|
69
|
+
PathItem.new(path, path_item_object, openapi_version:),
|
70
|
+
path_params
|
71
|
+
]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
42
75
|
def detect_version(resolved)
|
43
76
|
(resolved['openapi'] || resolved['swagger'])[0..2]
|
44
77
|
end
|
@@ -1,47 +1,40 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'forwardable'
|
4
|
-
|
5
3
|
module OpenapiFirst
|
6
|
-
# This is the base
|
7
|
-
|
8
|
-
## @param
|
9
|
-
|
10
|
-
|
11
|
-
@env = env
|
12
|
-
@request_validation_error = request_validation_error
|
4
|
+
# This is the base module for error responses
|
5
|
+
module ErrorResponse
|
6
|
+
## @param failure [OpenapiFirst::Failure]
|
7
|
+
def initialize(failure: nil)
|
8
|
+
@failure = failure
|
13
9
|
end
|
14
10
|
|
15
|
-
|
16
|
-
|
17
|
-
attr_reader :env, :request_validation_error
|
18
|
-
|
19
|
-
def_delegators :@request_validation_error, :status, :location, :schema_validation
|
11
|
+
attr_reader :failure
|
20
12
|
|
21
|
-
|
22
|
-
|
13
|
+
# The response body
|
14
|
+
def body
|
15
|
+
raise NotImplementedError
|
23
16
|
end
|
24
17
|
|
25
|
-
|
26
|
-
|
18
|
+
# The response content-type
|
19
|
+
def content_type
|
20
|
+
raise NotImplementedError
|
27
21
|
end
|
28
22
|
|
29
|
-
|
30
|
-
|
31
|
-
|
23
|
+
STATUS = {
|
24
|
+
not_found: 404,
|
25
|
+
method_not_allowed: 405,
|
26
|
+
unsupported_media_type: 415
|
27
|
+
}.freeze
|
28
|
+
private_constant :STATUS
|
32
29
|
|
33
|
-
|
34
|
-
|
30
|
+
# The response status
|
31
|
+
def status
|
32
|
+
STATUS[failure.error_type] || 400
|
35
33
|
end
|
36
34
|
|
35
|
+
# Render this error response
|
37
36
|
def render
|
38
37
|
Rack::Response.new(body, status, Rack::CONTENT_TYPE => content_type).finish
|
39
38
|
end
|
40
|
-
|
41
|
-
def content_type = 'application/json'
|
42
|
-
|
43
|
-
def body
|
44
|
-
raise NotImplementedError
|
45
|
-
end
|
46
39
|
end
|
47
40
|
end
|
data/lib/openapi_first/errors.rb
CHANGED
@@ -2,20 +2,8 @@
|
|
2
2
|
|
3
3
|
module OpenapiFirst
|
4
4
|
class Error < StandardError; end
|
5
|
-
|
6
5
|
class NotFoundError < Error; end
|
7
|
-
|
8
|
-
class ResponseInvalid < Error; end
|
9
|
-
|
10
|
-
class ResponseCodeNotFoundError < ResponseInvalid; end
|
11
|
-
|
12
|
-
class ResponseContentTypeNotFoundError < ResponseInvalid; end
|
13
|
-
|
14
|
-
class ResponseBodyInvalidError < ResponseInvalid; end
|
15
|
-
|
16
|
-
class ResponseHeaderInvalidError < ResponseInvalid; end
|
17
|
-
|
18
|
-
class BodyParsingError < Error; end
|
19
|
-
|
20
6
|
class RequestInvalidError < Error; end
|
7
|
+
class ResponseNotFoundError < Error; end
|
8
|
+
class ResponseInvalidError < Error; end
|
21
9
|
end
|