Skip to content

Commit 6d6637a

Browse files
committed
fixup! fix(@angular/ssr): prevent redirect loop with encoded query parameters
1 parent f75a209 commit 6d6637a

File tree

2 files changed

+18
-8
lines changed

2 files changed

+18
-8
lines changed

packages/angular/ssr/src/utils/ng.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9-
import { PlatformLocation } from '@angular/common';
9+
import { LocationStrategy } from '@angular/common';
1010
import {
1111
ApplicationRef,
1212
type PlatformRef,
@@ -21,9 +21,9 @@ import {
2121
platformServer,
2222
ɵrenderInternal as renderInternal,
2323
} from '@angular/platform-server';
24-
import { ActivatedRoute, Router } from '@angular/router';
24+
import { ActivatedRoute, Router, UrlSerializer } from '@angular/router';
2525
import { Console } from '../console';
26-
import { stripIndexHtmlFromURL, stripTrailingSlash } from './url';
26+
import { stripIndexHtmlFromURL } from './url';
2727

2828
/**
2929
* Represents the bootstrap mechanism for an Angular application.
@@ -107,11 +107,14 @@ export async function renderAngular(
107107

108108
if (!routerIsProvided) {
109109
hasNavigationError = false;
110-
} else if (lastSuccessfulNavigation) {
110+
} else if (lastSuccessfulNavigation?.finalUrl) {
111111
hasNavigationError = false;
112-
const { pathname, search, hash } = envInjector.get(PlatformLocation);
113-
const finalUrl = [stripTrailingSlash(pathname), search, hash].join('');
114-
const finalUrlHref = decodeURIComponent(new URL(finalUrl, urlToRender.origin).href);
112+
113+
const urlSerializer = envInjector.get(UrlSerializer);
114+
const finalUrlSerialized = urlSerializer.serialize(lastSuccessfulNavigation.finalUrl);
115+
const locationStrategy = envInjector.get(LocationStrategy);
116+
const finalUrl = locationStrategy.prepareExternalUrl(finalUrlSerialized);
117+
const finalUrlHref = new URL(finalUrl, urlToRender.origin).href;
115118
const urlToRenderHref = decodeURIComponent(urlToRender.href);
116119

117120
if (urlToRenderHref !== finalUrlHref) {

packages/angular/ssr/test/app-engine_spec.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,11 +270,18 @@ describe('AngularAppEngine', () => {
270270
expect(await response?.text()).toContain('Home works');
271271
});
272272

273-
it('should not decode query parameters', async () => {
273+
it('should work with encoded characters', async () => {
274274
const request = new Request('https://example.com/home?email=xyz%40xyz.com');
275275
const response = await appEngine.handle(request);
276276
expect(response?.status).toBe(200);
277277
expect(await response?.text()).toContain('Home works');
278278
});
279+
280+
it('should work with decoded characters', async () => {
281+
const request = new Request('https://example.com/home?email=xyz@xyz.com');
282+
const response = await appEngine.handle(request);
283+
expect(response?.status).toBe(200);
284+
expect(await response?.text()).toContain('Home works');
285+
});
279286
});
280287
});

0 commit comments

Comments
 (0)