Skip to content

Commit 7931f8d

Browse files
authored
fix(nextjs): Fix parameterization for root catchall routes (#17489)
1 parent 499b79a commit 7931f8d

File tree

4 files changed

+42
-4
lines changed

4 files changed

+42
-4
lines changed

packages/nextjs/src/config/manifest/createRouteManifest.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,16 @@ function buildRegexForDynamicRoute(routePath: string): { regex: string; paramNam
7777

7878
let pattern: string;
7979
if (hasOptionalCatchall) {
80-
// For optional catchall, make the trailing slash and segments optional
81-
// This allows matching both /catchall and /catchall/anything
82-
const staticParts = regexSegments.join('/');
83-
pattern = `^/${staticParts}(?:/(.*))?$`;
80+
if (regexSegments.length === 0) {
81+
// If the optional catchall happens at the root, accept any path starting
82+
// with a slash. Need capturing group for parameter extraction.
83+
pattern = '^/(.*)$';
84+
} else {
85+
// For optional catchall, make the trailing slash and segments optional
86+
// This allows matching both /catchall and /catchall/anything
87+
const staticParts = regexSegments.join('/');
88+
pattern = `^/${staticParts}(?:/(.*))?$`;
89+
}
8490
} else {
8591
pattern = `^/${regexSegments.join('/')}$`;
8692
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// beep
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// Ciao
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import path from 'path';
2+
import { describe, expect, test } from 'vitest';
3+
import { createRouteManifest } from '../../../../../src/config/manifest/createRouteManifest';
4+
5+
describe('catchall', () => {
6+
const manifest = createRouteManifest({ appDirPath: path.join(__dirname, 'app') });
7+
8+
test('should generate a manifest with catchall route', () => {
9+
expect(manifest).toEqual({
10+
staticRoutes: [{ path: '/' }],
11+
dynamicRoutes: [
12+
{
13+
path: '/:path*?',
14+
regex: '^/(.*)$',
15+
paramNames: ['path'],
16+
},
17+
],
18+
});
19+
});
20+
21+
test('should generate correct pattern for catchall route', () => {
22+
const catchallRoute = manifest.dynamicRoutes.find(route => route.path === '/:path*?');
23+
const regex = new RegExp(catchallRoute?.regex ?? '');
24+
expect(regex.test('/123')).toBe(true);
25+
expect(regex.test('/abc')).toBe(true);
26+
expect(regex.test('/123/456')).toBe(true);
27+
expect(regex.test('/123/abc/789')).toBe(true);
28+
expect(regex.test('/')).toBe(true);
29+
});
30+
});

0 commit comments

Comments
 (0)