Skip to content

Commit 7ff2876

Browse files
authored
Fix prefix matching to respect path segment boundaries (#468)
This PR fixes prefix matching so a configured prefix like /v1 only matches /v1 and /v1/..., and does not incorrectly match /v11/....
1 parent d644a2e commit 7ff2876

File tree

6 files changed

+34
-2
lines changed

6 files changed

+34
-2
lines changed

lib/committee/schema_validator.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ def request_media_type(request)
1212
def build_prefix_regexp(prefix)
1313
return nil unless prefix
1414

15-
/\A#{Regexp.escape(prefix)}/.freeze
15+
if prefix == "/" || prefix.end_with?("/")
16+
/\A#{Regexp.escape(prefix)}/.freeze
17+
else
18+
/\A#{Regexp.escape(prefix)}(?=\/|\z)/.freeze
19+
end
1620
end
1721
end
1822
end

lib/committee/schema_validator/hyper_schema/router.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class HyperSchema
66
class Router
77
def initialize(schema, validator_option)
88
@prefix = validator_option.prefix
9-
@prefix_regexp = /\A#{Regexp.escape(@prefix)}/.freeze if @prefix
9+
@prefix_regexp = ::Committee::SchemaValidator.build_prefix_regexp(@prefix)
1010
@schema = schema
1111

1212
@validator_option = validator_option

test/middleware/request_validation_open_api_3_test.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,14 @@ def app
254254
assert_equal 200, last_response.status
255255
end
256256

257+
it "ignores similar prefix paths outside the prefix in strict mode" do
258+
@app = new_rack_app(prefix: "/v1", schema: open_api_3_schema, strict: true)
259+
params = { "string_post_1" => 1 }
260+
header "Content-Type", "application/json"
261+
post "/v11/characters", JSON.generate(params)
262+
assert_equal 200, last_response.status
263+
end
264+
257265
it "don't check prefix with no option" do
258266
@app = new_rack_app(schema: open_api_3_schema)
259267
params = { "string_post_1" => 1 }

test/middleware/request_validation_test.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,13 @@ def app
263263
assert_equal 200, last_response.status
264264
end
265265

266+
it "ignores similar prefix paths outside the prefix in strict mode" do
267+
@app = new_rack_app(prefix: "/v1", schema: hyper_schema, strict: true)
268+
header "Content-Type", "application/json"
269+
post "/v11/apps", JSON.generate({ "name" => 1 })
270+
assert_equal 200, last_response.status
271+
end
272+
266273
it "routes to paths not in schema" do
267274
@app = new_rack_app(schema: hyper_schema)
268275
get "/not-a-resource"

test/schema_validator/hyper_schema/router_test.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@
4343
refute_nil link
4444
end
4545

46+
it "does not include a similar prefix path segment" do
47+
link, _ = hyper_schema_router(prefix: "/kpi").includes?("/kpi2/apps")
48+
assert_nil link
49+
end
50+
4651
it "provides named parameters" do
4752
link, param_matches = open_api_2_router.find_link("GET", "/api/pets/fido")
4853
refute_nil link

test/schema_validator_test.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,12 @@
2020
media_type = Committee::SchemaValidator.request_media_type(request)
2121
assert_equal 'multipart/form-data', media_type
2222
end
23+
24+
it "builds prefix regexp with a path segment boundary" do
25+
regexp = Committee::SchemaValidator.build_prefix_regexp("/v1")
26+
27+
assert regexp.match?("/v1")
28+
assert regexp.match?("/v1/characters")
29+
refute regexp.match?("/v11/characters")
30+
end
2331
end

0 commit comments

Comments
 (0)