Skip to content

Commit 9650131

Browse files
dsilvamDaniel Silvaclaude
authored
fix(vanity-url): restore /c/ trailing slash in BACKEND_FILTERED_COLLECTION (#35354)
## Summary - Restores the trailing slash on \`/c/\` in \`CMSUrlUtil.BACKEND_FILTERED_COLLECTION\` — one character change: \`/c\` → \`/c/\` - \`isVanityUrlFiltered()\` uses raw \`url.startsWith(prefix)\`, so without the slash, prefix \`/c\` matches **any** URL beginning with the letter "c" (e.g. \`/calculators\`, \`/contact\`, \`/customers\`), causing \`VanityURLFilter\` to skip vanity URL resolution for those paths entirely - Confirmed broken in production on \`26.04.11-01_1007280\`, working on \`26.03.27-01_73a99ad\` ## Root Cause PR #35151 changed \`/c/\` to \`/c\` in \`BACKEND_FILTERED_COLLECTION\`. The \`internalUrl()\` method added in that PR appends \`"/"\` before calling \`startsWith()\` so it is safe — but the pre-existing \`isVanityUrlFiltered()\` does not, making \`/c\` an overly broad prefix that matches all \`c*\` URLs. ## Test plan - [ ] Request a vanity URL whose URI starts with \`c\` (e.g. \`/calculators/home-loan/mortgage-calculator\`) — should resolve correctly instead of returning 404 - [ ] Request \`/c/<uuid>/fileAsset/...\` (content asset endpoint) — should still be excluded as an internal URL - [ ] Run \`CMSUrlUtilTest\` — two new regression tests cover both cases 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Daniel Silva <infoserveisaudiovisuals@Daniel-Silva-MBP-M2.local> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent e8f92a1 commit 9650131

2 files changed

Lines changed: 26 additions & 1 deletion

File tree

dotCMS/src/main/java/com/dotmarketing/filters/CMSUrlUtil.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public class CMSUrlUtil {
6969
private static final String UNABLE_TO_FIND = "Unable to find ";
7070

7171
public static final Set<String> BACKEND_FILTERED_COLLECTION =
72-
Stream.of("/api", "/webdav", "/dA", "/c", "/contentAsset", "/DOTSASS", "/DOTLESS",
72+
Stream.of("/api", "/webdav", "/dA", "/c/", "/contentAsset", "/DOTSASS", "/DOTLESS",
7373
"/html", "/dotAdmin", "/custom-elements","/dotcms-webcomponents","/dwr")
7474
.collect(Collectors.collectingAndThen(toSet(), Collections::unmodifiableSet));
7575

dotCMS/src/test/java/com/dotmarketing/filters/CMSUrlUtilTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,31 @@ public void test_getIdentifierFromUrlPath() {
7878

7979
}
8080

81+
/**
82+
* Method To Test: {@link CMSUrlUtil#isVanityUrlFiltered(String)}
83+
* Given Scenario: URLs starting with "c" that are NOT the /c/ content asset endpoint
84+
* ExpectedResult: Must return false — regression guard for PR #35151 which changed /c/ to /c,
85+
* causing isVanityUrlFiltered() to match any URL beginning with "c".
86+
*/
87+
@Test
88+
public void testIsVanityUrlFiltered_vanityUrlsStartingWithC_shouldNotBeFiltered() {
89+
final CMSUrlUtil util = CMSUrlUtil.getInstance();
90+
assertFalse("Vanity URL /calculators should not be filtered", util.isVanityUrlFiltered("/calculators/home-loan/mortgage-calculator"));
91+
assertFalse("Vanity URL /contact should not be filtered", util.isVanityUrlFiltered("/contact"));
92+
assertFalse("Vanity URL /careers should not be filtered", util.isVanityUrlFiltered("/careers/open-positions"));
93+
}
94+
95+
/**
96+
* Method To Test: {@link CMSUrlUtil#isVanityUrlFiltered(String)}
97+
* Given Scenario: The internal /c/ content asset endpoint
98+
* ExpectedResult: Must return true so the internal endpoint is still excluded
99+
*/
100+
@Test
101+
public void testIsVanityUrlFiltered_contentAssetEndpoint_shouldBeFiltered() {
102+
final CMSUrlUtil util = CMSUrlUtil.getInstance();
103+
assertTrue("Internal /c/ endpoint should be filtered", util.isVanityUrlFiltered("/c/uuid-here/fileAsset/file.vtl"));
104+
}
105+
81106
/**
82107
* Given scenario: Test the request comes from dotAdmin
83108
* Expected result: Should return true if the referer is a valid dotAdmin referer

0 commit comments

Comments
 (0)