fix(router): Do not modify parts of URL excluded from with 'eager' updates (#43421)

The previous code would set the browser URL to be only the part that's
extracted by the `UrlHandlingStrategy`. However, there may be parts of
the URL which are _should not_ be handled by the Angular Router. This
change updates the code to set the browser URL in the same way that's
done with `'deferred'`: Merging the extracted URL after redirects with
the whole raw URL of the navigation, which includes parts not handled by
the `UrlHandlingStrategy`.

PR Close #43421
This commit is contained in:
Andrew Scott
2021-09-10 10:03:50 -07:00
committed by Andrew Kushnir
parent e8e41efcea
commit 796da641f0
2 changed files with 12 additions and 22 deletions
+3 -8
View File
@@ -715,14 +715,9 @@ export class Router {
tap(t => {
if (this.urlUpdateStrategy === 'eager') {
if (!t.extras.skipLocationChange) {
this.setBrowserUrl(t.urlAfterRedirects, t);
// TODO(atscott): The above line is incorrect. It sets the url to
// only the part that is handled by the router. It should merge
// that with the rawUrl so the url includes segments not handled
// by the router:
// const rawUrl = this.urlHandlingStrategy.merge(
// t.urlAfterRedirects, t.rawUrl);
// this.setBrowserUrl(rawUrl, t);
const rawUrl = this.urlHandlingStrategy.merge(
t.urlAfterRedirects, t.rawUrl);
this.setBrowserUrl(rawUrl, t);
}
this.browserUrlTree = t.urlAfterRedirects;
}
+9 -14
View File
@@ -5647,28 +5647,23 @@ describe('Integration', () => {
]);
})));
it('should not reset parts of the URL not handled by the router', fakeAsync(() => {
const location = TestBed.inject(Location) as SpyLocation;
it('should not remove parts of the URL that are not handled by the router when "eager"',
fakeAsync(() => {
const router = TestBed.inject(Router);
router.urlUpdateStrategy = 'eager';
const location = TestBed.inject(Location) as SpyLocation;
const fixture = createRoot(router, RootCmp);
router.resetConfig([{
path: 'include',
component: TeamCmp,
children:
[{path: 'user/:name', component: UserCmp}, {path: 'simple', component: SimpleCmp}]
children: [{path: 'user/:name', component: UserCmp}]
}]);
try {
location.simulateHashChange('/include/butThisPartNotFound(aux:excluded)');
advance(fixture);
} catch (e) {
}
// The router only handled the primary URL. So it processes the navigation and then
// cannot match the `butThisPartNotFound` part to a URL, throws an error, and then
// resets the state in the `catchError` block. The excluded part of the URL _should not_
// be reset because it might be handled by another application.
expect(location.path()).toEqual('/(aux:excluded)');
location.simulateHashChange('/include/user/kate(aux:excluded)');
advance(fixture);
expect(location.path()).toEqual('/include/user/kate(aux:excluded)');
}));
});