Skip to content

Commit c68d772

Browse files
committed
fix(@angular-devkit/build-angular): construct SSR request URL using server resolvedUrls
With vite `header.host` is undefined when SSL is enabled. This resulted in an invalid URL to be constructed. Closes angular#26652
1 parent 5370b03 commit c68d772

File tree

3 files changed

+85
-3
lines changed

3 files changed

+85
-3
lines changed

packages/angular_devkit/build_angular/src/builders/dev-server/vite-server.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -680,11 +680,9 @@ export async function setupServer(
680680
}
681681

682682
transformIndexHtmlAndAddHeaders(url, rawHtml, res, next, async (html) => {
683-
const protocol = serverOptions.ssl ? 'https' : 'http';
684-
const route = `${protocol}://${req.headers.host}${req.originalUrl}`;
685683
const { content } = await renderPage({
686684
document: html,
687-
route,
685+
route: new URL(req.originalUrl ?? '/', server.resolvedUrls?.local[0]).toString(),
688686
serverContext: 'ssr',
689687
loadBundle: (uri: string) =>
690688
// eslint-disable-next-line @typescript-eslint/no-explicit-any

tests/legacy-cli/e2e.bzl

+4
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,17 @@ ESBUILD_TESTS = [
3333
"tests/build/**",
3434
"tests/commands/add/**",
3535
"tests/commands/e2e/**",
36+
"tests/commands/serve/ssr-http-requests-assets.js",
3637
"tests/i18n/**",
3738
"tests/vite/**",
3839
"tests/test/**",
3940
]
4041

4142
WEBPACK_IGNORE_TESTS = [
4243
"tests/vite/**",
44+
"tests/commands/serve/error-with-sourcemaps.js",
45+
"tests/commands/serve/ssr-http-requests-assets.js",
46+
"tests/build/prerender/http-requests-assets.js",
4347
]
4448

4549
def _to_glob(patterns):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import assert from 'node:assert';
2+
3+
import { killAllProcesses, ng } from '../../../utils/process';
4+
import { rimraf, writeMultipleFiles } from '../../../utils/fs';
5+
import { installWorkspacePackages } from '../../../utils/packages';
6+
import { ngServe, useSha } from '../../../utils/project';
7+
8+
export default async function () {
9+
// Forcibly remove in case another test doesn't clean itself up.
10+
await rimraf('node_modules/@angular/ssr');
11+
await ng('add', '@angular/ssr', '--skip-confirmation');
12+
await useSha();
13+
await installWorkspacePackages();
14+
15+
await writeMultipleFiles({
16+
// Add http client and route
17+
'src/app/app.config.ts': `
18+
import { ApplicationConfig } from '@angular/core';
19+
import { provideRouter } from '@angular/router';
20+
21+
import {HomeComponent} from './home/home.component';
22+
import { provideClientHydration } from '@angular/platform-browser';
23+
import { provideHttpClient, withFetch } from '@angular/common/http';
24+
25+
export const appConfig: ApplicationConfig = {
26+
providers: [
27+
provideRouter([{
28+
path: '',
29+
component: HomeComponent,
30+
}]),
31+
provideClientHydration(),
32+
provideHttpClient(withFetch()),
33+
],
34+
};
35+
`,
36+
// Add asset
37+
'src/assets/media.json': JSON.stringify({ dataFromAssets: true }),
38+
// Update component to do an HTTP call to asset.
39+
'src/app/app.component.ts': `
40+
import { Component, inject } from '@angular/core';
41+
import { CommonModule } from '@angular/common';
42+
import { RouterOutlet } from '@angular/router';
43+
import { HttpClient } from '@angular/common/http';
44+
45+
@Component({
46+
selector: 'app-root',
47+
standalone: true,
48+
imports: [CommonModule, RouterOutlet],
49+
template: \`
50+
<p>{{ data | json }}</p>
51+
<router-outlet></router-outlet>
52+
\`,
53+
})
54+
export class AppComponent {
55+
data: any;
56+
constructor() {
57+
const http = inject(HttpClient);
58+
http.get('/assets/media.json').toPromise().then((d) => {
59+
this.data = d;
60+
});
61+
}
62+
}
63+
`,
64+
});
65+
66+
await ng('generate', 'component', 'home');
67+
const match = /<p>{[\S\s]*"dataFromAssets":[\s\S]*true[\S\s]*}<\/p>/;
68+
const port = await ngServe('--no-ssl');
69+
assert.match(await (await fetch(`http://localhost:${port}/`)).text(), match);
70+
71+
await killAllProcesses();
72+
73+
try {
74+
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
75+
const sslPort = await ngServe('--ssl');
76+
assert.match(await (await fetch(`https://localhost:${sslPort}/`)).text(), match);
77+
} finally {
78+
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '1';
79+
}
80+
}

0 commit comments

Comments
 (0)