diff --git a/lib/committee/schema_validator.rb b/lib/committee/schema_validator.rb index 4885bbd3..de93d00c 100644 --- a/lib/committee/schema_validator.rb +++ b/lib/committee/schema_validator.rb @@ -12,7 +12,11 @@ def request_media_type(request) def build_prefix_regexp(prefix) return nil unless prefix - /\A#{Regexp.escape(prefix)}/.freeze + if prefix == "/" || prefix.end_with?("/") + /\A#{Regexp.escape(prefix)}/.freeze + else + /\A#{Regexp.escape(prefix)}(?=\/|\z)/.freeze + end end end end diff --git a/lib/committee/schema_validator/hyper_schema/router.rb b/lib/committee/schema_validator/hyper_schema/router.rb index 99bc7b83..e0748d64 100644 --- a/lib/committee/schema_validator/hyper_schema/router.rb +++ b/lib/committee/schema_validator/hyper_schema/router.rb @@ -6,7 +6,7 @@ class HyperSchema class Router def initialize(schema, validator_option) @prefix = validator_option.prefix - @prefix_regexp = /\A#{Regexp.escape(@prefix)}/.freeze if @prefix + @prefix_regexp = ::Committee::SchemaValidator.build_prefix_regexp(@prefix) @schema = schema @validator_option = validator_option diff --git a/test/middleware/request_validation_open_api_3_test.rb b/test/middleware/request_validation_open_api_3_test.rb index 32ef2ae0..f447daa5 100644 --- a/test/middleware/request_validation_open_api_3_test.rb +++ b/test/middleware/request_validation_open_api_3_test.rb @@ -254,6 +254,14 @@ def app assert_equal 200, last_response.status end + it "ignores similar prefix paths outside the prefix in strict mode" do + @app = new_rack_app(prefix: "/v1", schema: open_api_3_schema, strict: true) + params = { "string_post_1" => 1 } + header "Content-Type", "application/json" + post "/v11/characters", JSON.generate(params) + assert_equal 200, last_response.status + end + it "don't check prefix with no option" do @app = new_rack_app(schema: open_api_3_schema) params = { "string_post_1" => 1 } diff --git a/test/middleware/request_validation_test.rb b/test/middleware/request_validation_test.rb index adc07262..f4aa2ee7 100644 --- a/test/middleware/request_validation_test.rb +++ b/test/middleware/request_validation_test.rb @@ -263,6 +263,13 @@ def app assert_equal 200, last_response.status end + it "ignores similar prefix paths outside the prefix in strict mode" do + @app = new_rack_app(prefix: "/v1", schema: hyper_schema, strict: true) + header "Content-Type", "application/json" + post "/v11/apps", JSON.generate({ "name" => 1 }) + assert_equal 200, last_response.status + end + it "routes to paths not in schema" do @app = new_rack_app(schema: hyper_schema) get "/not-a-resource" diff --git a/test/schema_validator/hyper_schema/router_test.rb b/test/schema_validator/hyper_schema/router_test.rb index 41798516..aedc84c1 100644 --- a/test/schema_validator/hyper_schema/router_test.rb +++ b/test/schema_validator/hyper_schema/router_test.rb @@ -43,6 +43,11 @@ refute_nil link end + it "does not include a similar prefix path segment" do + link, _ = hyper_schema_router(prefix: "/kpi").includes?("/kpi2/apps") + assert_nil link + end + it "provides named parameters" do link, param_matches = open_api_2_router.find_link("GET", "/api/pets/fido") refute_nil link diff --git a/test/schema_validator_test.rb b/test/schema_validator_test.rb index 1bd5fb77..3cd48d36 100644 --- a/test/schema_validator_test.rb +++ b/test/schema_validator_test.rb @@ -20,4 +20,12 @@ media_type = Committee::SchemaValidator.request_media_type(request) assert_equal 'multipart/form-data', media_type end + + it "builds prefix regexp with a path segment boundary" do + regexp = Committee::SchemaValidator.build_prefix_regexp("/v1") + + assert regexp.match?("/v1") + assert regexp.match?("/v1/characters") + refute regexp.match?("/v11/characters") + end end