committee 3.1.0 → 3.1.1
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/bin/committee-stub +1 -0
- data/lib/committee.rb +12 -34
- data/lib/committee/bin/committee_stub.rb +6 -4
- data/lib/committee/drivers.rb +15 -67
- data/lib/committee/drivers/driver.rb +47 -0
- data/lib/committee/drivers/hyper_schema.rb +8 -171
- data/lib/committee/drivers/hyper_schema/driver.rb +105 -0
- data/lib/committee/drivers/hyper_schema/link.rb +68 -0
- data/lib/committee/drivers/hyper_schema/schema.rb +22 -0
- data/lib/committee/drivers/open_api_2.rb +9 -416
- data/lib/committee/drivers/open_api_2/driver.rb +253 -0
- data/lib/committee/drivers/open_api_2/header_schema_builder.rb +33 -0
- data/lib/committee/drivers/open_api_2/link.rb +36 -0
- data/lib/committee/drivers/open_api_2/parameter_schema_builder.rb +83 -0
- data/lib/committee/drivers/open_api_2/schema.rb +26 -0
- data/lib/committee/drivers/open_api_2/schema_builder.rb +33 -0
- data/lib/committee/drivers/open_api_3.rb +7 -75
- data/lib/committee/drivers/open_api_3/driver.rb +51 -0
- data/lib/committee/drivers/open_api_3/schema.rb +41 -0
- data/lib/committee/drivers/schema.rb +23 -0
- data/lib/committee/errors.rb +2 -0
- data/lib/committee/middleware.rb +11 -0
- data/lib/committee/middleware/base.rb +38 -34
- data/lib/committee/middleware/request_validation.rb +51 -30
- data/lib/committee/middleware/response_validation.rb +49 -26
- data/lib/committee/middleware/stub.rb +55 -51
- data/lib/committee/request_unpacker.rb +3 -1
- data/lib/committee/schema_validator.rb +23 -0
- data/lib/committee/schema_validator/hyper_schema.rb +85 -74
- data/lib/committee/schema_validator/hyper_schema/parameter_coercer.rb +60 -54
- data/lib/committee/schema_validator/hyper_schema/request_validator.rb +43 -37
- data/lib/committee/schema_validator/hyper_schema/response_generator.rb +86 -80
- data/lib/committee/schema_validator/hyper_schema/response_validator.rb +65 -59
- data/lib/committee/schema_validator/hyper_schema/router.rb +35 -29
- data/lib/committee/schema_validator/hyper_schema/string_params_coercer.rb +87 -81
- data/lib/committee/schema_validator/open_api_3.rb +71 -61
- data/lib/committee/schema_validator/open_api_3/operation_wrapper.rb +121 -115
- data/lib/committee/schema_validator/open_api_3/request_validator.rb +24 -18
- data/lib/committee/schema_validator/open_api_3/response_validator.rb +22 -16
- data/lib/committee/schema_validator/open_api_3/router.rb +30 -24
- data/lib/committee/schema_validator/option.rb +42 -38
- data/lib/committee/test/methods.rb +55 -51
- data/lib/committee/validation_error.rb +2 -0
- data/test/bin/committee_stub_test.rb +3 -1
- data/test/bin_test.rb +3 -1
- data/test/committee_test.rb +3 -1
- data/test/drivers/hyper_schema/driver_test.rb +49 -0
- data/test/drivers/{hyper_schema_test.rb → hyper_schema/link_test.rb} +2 -45
- data/test/drivers/open_api_2/driver_test.rb +156 -0
- data/test/drivers/open_api_2/header_schema_builder_test.rb +26 -0
- data/test/drivers/open_api_2/link_test.rb +52 -0
- data/test/drivers/open_api_2/parameter_schema_builder_test.rb +195 -0
- data/test/drivers/{open_api_3_test.rb → open_api_3/driver_test.rb} +5 -3
- data/test/drivers_test.rb +12 -10
- data/test/middleware/base_test.rb +3 -1
- data/test/middleware/request_validation_open_api_3_test.rb +4 -2
- data/test/middleware/request_validation_test.rb +46 -5
- data/test/middleware/response_validation_open_api_3_test.rb +3 -1
- data/test/middleware/response_validation_test.rb +39 -4
- data/test/middleware/stub_test.rb +3 -1
- data/test/request_unpacker_test.rb +2 -2
- data/test/schema_validator/hyper_schema/parameter_coercer_test.rb +2 -2
- data/test/schema_validator/hyper_schema/request_validator_test.rb +3 -1
- data/test/schema_validator/hyper_schema/response_generator_test.rb +3 -1
- data/test/schema_validator/hyper_schema/response_validator_test.rb +3 -1
- data/test/schema_validator/hyper_schema/router_test.rb +5 -3
- data/test/schema_validator/hyper_schema/string_params_coercer_test.rb +3 -1
- data/test/schema_validator/open_api_3/operation_wrapper_test.rb +3 -1
- data/test/schema_validator/open_api_3/request_validator_test.rb +11 -1
- data/test/schema_validator/open_api_3/response_validator_test.rb +3 -1
- data/test/test/methods_new_version_test.rb +3 -1
- data/test/test/methods_test.rb +4 -2
- data/test/test_helper.rb +16 -16
- data/test/validation_error_test.rb +3 -1
- metadata +52 -6
- data/lib/committee/schema_validator/schema_validator.rb +0 -15
- data/test/drivers/open_api_2_test.rb +0 -416
|
@@ -1,49 +1,55 @@
|
|
|
1
|
-
|
|
2
|
-
class SchemaValidator::HyperSchema::RequestValidator
|
|
3
|
-
def initialize(link, options = {})
|
|
4
|
-
@link = link
|
|
5
|
-
@check_content_type = options.fetch(:check_content_type, true)
|
|
6
|
-
@check_header = options.fetch(:check_header, true)
|
|
7
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
8
2
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
3
|
+
module Committee
|
|
4
|
+
module SchemaValidator
|
|
5
|
+
class HyperSchema
|
|
6
|
+
class RequestValidator
|
|
7
|
+
def initialize(link, options = {})
|
|
8
|
+
@link = link
|
|
9
|
+
@check_content_type = options.fetch(:check_content_type, true)
|
|
10
|
+
@check_header = options.fetch(:check_header, true)
|
|
16
11
|
end
|
|
17
|
-
end
|
|
18
12
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
13
|
+
def call(request, params, headers)
|
|
14
|
+
check_content_type!(request, params) if @check_content_type
|
|
15
|
+
if @link.schema
|
|
16
|
+
valid, errors = @link.schema.validate(params)
|
|
17
|
+
if !valid
|
|
18
|
+
errors = JsonSchema::SchemaError.aggregate(errors).join("\n")
|
|
19
|
+
raise InvalidRequest, "Invalid request.\n\n#{errors}"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
if @check_header && @link.respond_to?(:header_schema) && @link.header_schema
|
|
24
|
+
valid, errors = @link.header_schema.validate(headers)
|
|
25
|
+
if !valid
|
|
26
|
+
errors = JsonSchema::SchemaError.aggregate(errors).join("\n")
|
|
27
|
+
raise InvalidRequest, "Invalid request.\n\n#{errors}"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
24
30
|
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
31
|
|
|
28
|
-
|
|
32
|
+
private
|
|
29
33
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
def check_content_type!(request, data)
|
|
35
|
+
content_type = ::Committee::SchemaValidator.request_media_type(request)
|
|
36
|
+
if content_type && @link.enc_type && !empty_request?(request)
|
|
37
|
+
unless Rack::Mime.match?(content_type, @link.enc_type)
|
|
38
|
+
raise Committee::InvalidRequest,
|
|
39
|
+
%{"Content-Type" request header must be set to "#{@link.enc_type}".}
|
|
40
|
+
end
|
|
41
|
+
end
|
|
36
42
|
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
43
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
44
|
+
def empty_request?(request)
|
|
45
|
+
# small optimization: assume GET and DELETE don't have bodies
|
|
46
|
+
return true if request.get? || request.delete? || !request.body
|
|
43
47
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
data = request.body.read
|
|
49
|
+
request.body.rewind
|
|
50
|
+
data.empty?
|
|
51
|
+
end
|
|
52
|
+
end
|
|
47
53
|
end
|
|
48
54
|
end
|
|
49
55
|
end
|
|
@@ -1,95 +1,101 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Committee
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
#
|
|
9
|
-
# This is poor form that's here so as not to introduce breaking behavior.
|
|
10
|
-
# The "instances" value of "rel" is a Heroku-ism and was originally
|
|
11
|
-
# introduced before we understood how to use "targetSchema". It's not
|
|
12
|
-
# meaningful with the context of the hyper-schema specification and
|
|
13
|
-
# should be eventually be removed.
|
|
14
|
-
if legacy_hyper_schema_rel?(link)
|
|
15
|
-
data = [data]
|
|
16
|
-
end
|
|
4
|
+
module SchemaValidator
|
|
5
|
+
class HyperSchema
|
|
6
|
+
class ResponseGenerator
|
|
7
|
+
def call(link)
|
|
8
|
+
schema = target_schema(link)
|
|
9
|
+
data = generate_properties(link, schema)
|
|
17
10
|
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
# List is a special case; wrap data in an array.
|
|
12
|
+
#
|
|
13
|
+
# This is poor form that's here so as not to introduce breaking behavior.
|
|
14
|
+
# The "instances" value of "rel" is a Heroku-ism and was originally
|
|
15
|
+
# introduced before we understood how to use "targetSchema". It's not
|
|
16
|
+
# meaningful with the context of the hyper-schema specification and
|
|
17
|
+
# should be eventually be removed.
|
|
18
|
+
if legacy_hyper_schema_rel?(link)
|
|
19
|
+
data = [data]
|
|
20
|
+
end
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
# These are basic types that are part of the JSON schema for which we'll
|
|
24
|
-
# emit zero values when generating a response. For a schema that allows
|
|
25
|
-
# multiple of the types in the list, types are preferred in the order in
|
|
26
|
-
# which they're defined.
|
|
27
|
-
SCALAR_TYPES = {
|
|
28
|
-
"boolean" => false,
|
|
29
|
-
"integer" => 0,
|
|
30
|
-
"number" => 0.0,
|
|
31
|
-
"string" => "",
|
|
32
|
-
|
|
33
|
-
# Prefer null last.
|
|
34
|
-
"null" => nil,
|
|
35
|
-
}.freeze
|
|
36
|
-
|
|
37
|
-
def generate_properties(link, schema)
|
|
38
|
-
# special example attribute was included; use its value
|
|
39
|
-
if schema.data && !schema.data["example"].nil?
|
|
40
|
-
schema.data["example"]
|
|
41
|
-
|
|
42
|
-
elsif !schema.all_of.empty? || !schema.properties.empty?
|
|
43
|
-
data = {}
|
|
44
|
-
schema.all_of.each do |subschema|
|
|
45
|
-
data.merge!(generate_properties(link, subschema))
|
|
46
|
-
end
|
|
47
|
-
schema.properties.map do |key, value|
|
|
48
|
-
data[key] = generate_properties(link, value)
|
|
22
|
+
[data, schema]
|
|
49
23
|
end
|
|
50
|
-
data
|
|
51
24
|
|
|
52
|
-
|
|
53
|
-
[generate_properties(link, schema.items)]
|
|
25
|
+
private
|
|
54
26
|
|
|
55
|
-
|
|
56
|
-
schema
|
|
27
|
+
# These are basic types that are part of the JSON schema for which we'll
|
|
28
|
+
# emit zero values when generating a response. For a schema that allows
|
|
29
|
+
# multiple of the types in the list, types are preferred in the order in
|
|
30
|
+
# which they're defined.
|
|
31
|
+
SCALAR_TYPES = {
|
|
32
|
+
"boolean" => false,
|
|
33
|
+
"integer" => 0,
|
|
34
|
+
"number" => 0.0,
|
|
35
|
+
"string" => "",
|
|
57
36
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
end
|
|
37
|
+
# Prefer null last.
|
|
38
|
+
"null" => nil,
|
|
39
|
+
}.freeze
|
|
62
40
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
41
|
+
def generate_properties(link, schema)
|
|
42
|
+
# special example attribute was included; use its value
|
|
43
|
+
if schema.data && !schema.data["example"].nil?
|
|
44
|
+
schema.data["example"]
|
|
66
45
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
46
|
+
elsif !schema.all_of.empty? || !schema.properties.empty?
|
|
47
|
+
data = {}
|
|
48
|
+
schema.all_of.each do |subschema|
|
|
49
|
+
data.merge!(generate_properties(link, subschema))
|
|
50
|
+
end
|
|
51
|
+
schema.properties.map do |key, value|
|
|
52
|
+
data[key] = generate_properties(link, value)
|
|
53
|
+
end
|
|
54
|
+
data
|
|
70
55
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
%{"example" attribute and "null" } +
|
|
74
|
-
%{is not allowed; don't know how to generate property.})
|
|
75
|
-
end
|
|
76
|
-
end
|
|
56
|
+
elsif schema.type.include?("array") && !schema.items.nil?
|
|
57
|
+
[generate_properties(link, schema.items)]
|
|
77
58
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
link.rel == "instances" &&
|
|
81
|
-
!link.target_schema
|
|
82
|
-
end
|
|
59
|
+
elsif schema.enum
|
|
60
|
+
schema.enum.first
|
|
83
61
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
62
|
+
elsif schema.type.any? { |t| SCALAR_TYPES.include?(t) }
|
|
63
|
+
SCALAR_TYPES.each do |k, v|
|
|
64
|
+
break(v) if schema.type.include?(k)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Generate an empty array for arrays.
|
|
68
|
+
elsif schema.type == ["array"]
|
|
69
|
+
[]
|
|
70
|
+
|
|
71
|
+
# Schema is an object with no properties: just generate an empty object.
|
|
72
|
+
elsif schema.type == ["object"]
|
|
73
|
+
{}
|
|
74
|
+
|
|
75
|
+
else
|
|
76
|
+
raise(%{At "#{link.method} #{link.href}" "#{schema.pointer}": no } +
|
|
77
|
+
%{"example" attribute and "null" } +
|
|
78
|
+
%{is not allowed; don't know how to generate property.})
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def legacy_hyper_schema_rel?(link)
|
|
83
|
+
link.is_a?(Committee::Drivers::HyperSchema::Link) &&
|
|
84
|
+
link.rel == "instances" &&
|
|
85
|
+
!link.target_schema
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Gets the target schema of a link. This is normally just the standard
|
|
89
|
+
# response schema, but we allow some legacy behavior for hyper-schema links
|
|
90
|
+
# tagged with rel=instances to instead use the schema of their parent
|
|
91
|
+
# resource.
|
|
92
|
+
def target_schema(link)
|
|
93
|
+
if link.target_schema
|
|
94
|
+
link.target_schema
|
|
95
|
+
elsif legacy_hyper_schema_rel?(link)
|
|
96
|
+
link.parent
|
|
97
|
+
end
|
|
98
|
+
end
|
|
93
99
|
end
|
|
94
100
|
end
|
|
95
101
|
end
|
|
@@ -1,76 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Committee
|
|
2
|
-
|
|
3
|
-
|
|
4
|
+
module SchemaValidator
|
|
5
|
+
class HyperSchema
|
|
6
|
+
class ResponseValidator
|
|
7
|
+
attr_reader :validate_success_only
|
|
4
8
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
9
|
+
def initialize(link, options = {})
|
|
10
|
+
@link = link
|
|
11
|
+
@validate_success_only = options[:validate_success_only]
|
|
8
12
|
|
|
9
|
-
|
|
10
|
-
|
|
13
|
+
@validator = JsonSchema::Validator.new(target_schema(link))
|
|
14
|
+
end
|
|
11
15
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
def call(status, headers, data)
|
|
17
|
+
unless status == 204 # 204 No Content
|
|
18
|
+
response = Rack::Response.new(data, status, headers)
|
|
19
|
+
check_content_type!(response)
|
|
20
|
+
end
|
|
17
21
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
# List is a special case; expect data in an array.
|
|
23
|
+
#
|
|
24
|
+
# This is poor form that's here so as not to introduce breaking behavior.
|
|
25
|
+
# The "instances" value of "rel" is a Heroku-ism and was originally
|
|
26
|
+
# introduced before we understood how to use "targetSchema". It's not
|
|
27
|
+
# meaningful with the context of the hyper-schema specification and
|
|
28
|
+
# should be eventually be removed.
|
|
29
|
+
if legacy_hyper_schema_rel?(@link)
|
|
30
|
+
if !data.is_a?(Array)
|
|
31
|
+
raise InvalidResponse, "List endpoints must return an array of objects."
|
|
32
|
+
end
|
|
29
33
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
# only consider the first object during the validation from here on
|
|
35
|
+
# (but only in cases where `targetSchema` is not set)
|
|
36
|
+
data = data[0]
|
|
33
37
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
# if the array was empty, allow it through
|
|
39
|
+
return if data == nil
|
|
40
|
+
end
|
|
37
41
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
if Committee::Middleware::ResponseValidation.validate?(status, validate_success_only) && !@validator.validate(data)
|
|
43
|
+
errors = JsonSchema::SchemaError.aggregate(@validator.errors).join("\n")
|
|
44
|
+
raise InvalidResponse, "Invalid response.\n\n#{errors}"
|
|
45
|
+
end
|
|
46
|
+
end
|
|
43
47
|
|
|
44
|
-
|
|
48
|
+
private
|
|
45
49
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
def response_media_type(response)
|
|
51
|
+
response.content_type.to_s.split(";").first.to_s
|
|
52
|
+
end
|
|
49
53
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
def check_content_type!(response)
|
|
55
|
+
if @link.media_type
|
|
56
|
+
unless Rack::Mime.match?(response_media_type(response), @link.media_type)
|
|
57
|
+
raise Committee::InvalidResponse,
|
|
58
|
+
%{"Content-Type" response header must be set to "#{@link.media_type}".}
|
|
59
|
+
end
|
|
60
|
+
end
|
|
55
61
|
end
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
62
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
def legacy_hyper_schema_rel?(link)
|
|
64
|
+
link.is_a?(Committee::Drivers::HyperSchema::Link) &&
|
|
65
|
+
link.rel == "instances" &&
|
|
66
|
+
!link.target_schema
|
|
67
|
+
end
|
|
64
68
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
# Gets the target schema of a link. This is normally just the standard
|
|
70
|
+
# response schema, but we allow some legacy behavior for hyper-schema links
|
|
71
|
+
# tagged with rel=instances to instead use the schema of their parent
|
|
72
|
+
# resource.
|
|
73
|
+
def target_schema(link)
|
|
74
|
+
if link.target_schema
|
|
75
|
+
link.target_schema
|
|
76
|
+
elsif legacy_hyper_schema_rel?(link)
|
|
77
|
+
link.parent
|
|
78
|
+
end
|
|
79
|
+
end
|
|
74
80
|
end
|
|
75
81
|
end
|
|
76
82
|
end
|
|
@@ -1,40 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Committee
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
module SchemaValidator
|
|
5
|
+
class HyperSchema
|
|
6
|
+
class Router
|
|
7
|
+
def initialize(schema, validator_option)
|
|
8
|
+
@prefix = validator_option.prefix
|
|
9
|
+
@prefix_regexp = /\A#{Regexp.escape(@prefix)}/.freeze if @prefix
|
|
10
|
+
@schema = schema
|
|
7
11
|
|
|
8
|
-
|
|
9
|
-
|
|
12
|
+
@validator_option = validator_option
|
|
13
|
+
end
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
def includes?(path)
|
|
16
|
+
!@prefix || path =~ @prefix_regexp
|
|
17
|
+
end
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
19
|
+
def includes_request?(request)
|
|
20
|
+
includes?(request.path)
|
|
21
|
+
end
|
|
18
22
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
def find_link(method, path)
|
|
24
|
+
path = path.gsub(@prefix_regexp, "") if @prefix
|
|
25
|
+
link_with_matches = (@schema.routes[method] || []).map do |pattern, link|
|
|
26
|
+
if matches = pattern.match(path)
|
|
27
|
+
# prefer path which has fewer matches (eg. `/pets/dog` than `/pets/{uuid}` for path `/pets/dog` )
|
|
28
|
+
[matches.captures.size, link, Hash[matches.names.zip(matches.captures)]]
|
|
29
|
+
else
|
|
30
|
+
nil
|
|
31
|
+
end
|
|
32
|
+
end.compact.sort_by(&:first).first
|
|
33
|
+
link_with_matches.nil? ? nil : link_with_matches.slice(1, 2)
|
|
27
34
|
end
|
|
28
|
-
end.compact.sort_by(&:first).first
|
|
29
|
-
link_with_matches.nil? ? nil : link_with_matches.slice(1, 2)
|
|
30
|
-
end
|
|
31
35
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
def find_request_link(request)
|
|
37
|
+
find_link(request.request_method, request.path_info)
|
|
38
|
+
end
|
|
35
39
|
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
def build_schema_validator(request)
|
|
41
|
+
Committee::SchemaValidator::HyperSchema.new(self, request, @validator_option)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
38
44
|
end
|
|
39
45
|
end
|
|
40
46
|
end
|