Skip to content

Commit 683697e

Browse files
committed
fix(@angular/ssr): improve route matching for wildcard routes
Enhance the route traversal logic to correctly identify and process wildcard route matchers (e.g., '**'). This ensures that routes with matchers are properly marked as present in the client router and handled according to their render mode. closes #31666 (cherry picked from commit 4eb22bc)
1 parent 08e07e3 commit 683697e

File tree

2 files changed

+52
-6
lines changed

2 files changed

+52
-6
lines changed

packages/angular/ssr/src/routes/ng-routes.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -256,15 +256,22 @@ async function* traverseRoutesConfig(options: {
256256
const currentRoutePath = joinUrlParts(parentRoute, path);
257257

258258
if (matcher && serverConfigRouteTree) {
259-
let foundMatch = false;
259+
const matches: (RouteTreeNodeMetadata & ServerConfigRouteTreeAdditionalMetadata)[] = [];
260260
for (const matchedMetaData of serverConfigRouteTree.traverse()) {
261-
if (!matchedMetaData.route.startsWith(currentRoutePath)) {
262-
continue;
261+
if (matchedMetaData.route.startsWith(currentRoutePath)) {
262+
matches.push(matchedMetaData);
263263
}
264+
}
264265

265-
foundMatch = true;
266-
matchedMetaData.presentInClientRouter = true;
266+
if (!matches.length) {
267+
const matchedMetaData = serverConfigRouteTree.match(currentRoutePath);
268+
if (matchedMetaData) {
269+
matches.push(matchedMetaData);
270+
}
271+
}
267272

273+
for (const matchedMetaData of matches) {
274+
matchedMetaData.presentInClientRouter = true;
268275
if (matchedMetaData.renderMode === RenderMode.Prerender) {
269276
yield {
270277
error:
@@ -287,7 +294,7 @@ async function* traverseRoutesConfig(options: {
287294
});
288295
}
289296

290-
if (!foundMatch) {
297+
if (!matches.length) {
291298
yield {
292299
error:
293300
`The route '${stripLeadingSlash(currentRoutePath)}' has a defined matcher but does not ` +

packages/angular/ssr/test/routes/ng-routes_spec.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,45 @@ describe('extractRoutesAndCreateRouteTree', () => {
429429
]);
430430
});
431431

432+
it('should extract routes with a route level matcher captured by "**"', async () => {
433+
setAngularAppTestingManifest(
434+
[
435+
{
436+
path: '',
437+
component: DummyComponent,
438+
},
439+
{
440+
path: 'list',
441+
component: DummyComponent,
442+
},
443+
{
444+
path: 'product',
445+
component: DummyComponent,
446+
children: [
447+
{
448+
matcher: () => null,
449+
component: DummyComponent,
450+
},
451+
],
452+
},
453+
],
454+
[
455+
{ path: 'list', renderMode: RenderMode.Client },
456+
{ path: '', renderMode: RenderMode.Client },
457+
{ path: '**', renderMode: RenderMode.Server },
458+
],
459+
);
460+
461+
const { routeTree, errors } = await extractRoutesAndCreateRouteTree({ url });
462+
expect(errors).toHaveSize(0);
463+
expect(routeTree.toObject()).toEqual([
464+
{ route: '/', renderMode: RenderMode.Client },
465+
{ route: '/list', renderMode: RenderMode.Client },
466+
{ route: '/product', renderMode: RenderMode.Server },
467+
{ route: '/**', renderMode: RenderMode.Server },
468+
]);
469+
});
470+
432471
it('should extract nested redirects that are not explicitly defined.', async () => {
433472
setAngularAppTestingManifest(
434473
[

0 commit comments

Comments
 (0)