Skip to content

Commit fa882e4

Browse files
nicohrubecclaude
andcommitted
fix: Handle splat/catch-all routes in URL pattern matching
A bare `$` segment matches multiple path segments (e.g., `/files/$` matches `/files/a/b/c`). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 055babe commit fa882e4

2 files changed

Lines changed: 15 additions & 0 deletions

File tree

packages/tanstackstart-react/src/server/routeParametrization.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ function patternToRegex(pattern: string): RegExp {
99
const segments = pattern
1010
.split('/')
1111
.map(segment => {
12+
if (segment === '$') {
13+
return '.+';
14+
}
1215
if (segment.startsWith('$')) {
1316
return '[^/]+';
1417
}

packages/tanstackstart-react/test/server/routeParametrization.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,16 @@ describe('matchUrlToRoutePattern', () => {
4141
const patternsNested = ['/users/$id', '/users/$id/profile'];
4242
expect(matchUrlToRoutePattern('/users/123/profile', patternsNested)).toBe('/users/$id/profile');
4343
});
44+
45+
it('matches splat/catch-all routes across multiple segments', () => {
46+
const patternsWithSplat = ['/', '/files/$'];
47+
expect(matchUrlToRoutePattern('/files/a/b/c', patternsWithSplat)).toBe('/files/$');
48+
expect(matchUrlToRoutePattern('/files/readme.txt', patternsWithSplat)).toBe('/files/$');
49+
});
50+
51+
it('prefers specific routes over splat routes', () => {
52+
const patternsWithSplat = ['/files/$', '/files/upload'];
53+
expect(matchUrlToRoutePattern('/files/upload', patternsWithSplat)).toBe('/files/upload');
54+
expect(matchUrlToRoutePattern('/files/a/b', patternsWithSplat)).toBe('/files/$');
55+
});
4456
});

0 commit comments

Comments
 (0)