Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 1850f7b

Browse filesBrowse files
committed
fix(@angular/build): simplify SSL handling for with SSR
This commit simplifies the handling of self-signed SSL certificates for with SSR. Previously, tests and potentially users had to set or configure to bypass certificate validation issues with self-signed certificates. Closes #31710
1 parent c3c9ac5 commit 1850f7b
Copy full SHA for 1850f7b

File tree

Expand file treeCollapse file tree

14 files changed

+238
-64
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

14 files changed

+238
-64
lines changed
Open diff view settings
Collapse file

‎package.json‎

Copy file name to clipboardExpand all lines: package.json
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@
169169
}
170170
},
171171
"resolutions": {
172-
"typescript": "5.9.3"
172+
"typescript": "5.9.3",
173+
"undici-types": "^7.16.0"
173174
}
174175
}
Collapse file

‎packages/angular/build/BUILD.bazel‎

Copy file name to clipboardExpand all lines: packages/angular/build/BUILD.bazel
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ ts_project(
105105
":node_modules/sass",
106106
":node_modules/source-map-support",
107107
":node_modules/tinyglobby",
108+
":node_modules/undici",
108109
":node_modules/vite",
109110
":node_modules/vitest",
110111
":node_modules/watchpack",
Collapse file

‎packages/angular/build/package.json‎

Copy file name to clipboardExpand all lines: packages/angular/build/package.json
+3-2Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,16 @@
4242
"semver": "7.7.3",
4343
"source-map-support": "0.5.21",
4444
"tinyglobby": "0.2.15",
45+
"undici": "7.16.0",
4546
"vite": "7.1.12",
4647
"watchpack": "2.4.4"
4748
},
4849
"optionalDependencies": {
4950
"lmdb": "3.4.3"
5051
},
5152
"devDependencies": {
52-
"@angular/ssr": "workspace:*",
5353
"@angular-devkit/core": "workspace:*",
54+
"@angular/ssr": "workspace:*",
5455
"jsdom": "27.1.0",
5556
"less": "4.4.2",
5657
"ng-packagr": "21.0.0-rc.0",
@@ -59,9 +60,9 @@
5960
"vitest": "4.0.7"
6061
},
6162
"peerDependencies": {
62-
"@angular/core": "0.0.0-ANGULAR-FW-PEER-DEP",
6363
"@angular/compiler": "0.0.0-ANGULAR-FW-PEER-DEP",
6464
"@angular/compiler-cli": "0.0.0-ANGULAR-FW-PEER-DEP",
65+
"@angular/core": "0.0.0-ANGULAR-FW-PEER-DEP",
6566
"@angular/localize": "0.0.0-ANGULAR-FW-PEER-DEP",
6667
"@angular/platform-browser": "0.0.0-ANGULAR-FW-PEER-DEP",
6768
"@angular/platform-server": "0.0.0-ANGULAR-FW-PEER-DEP",
Collapse file

‎packages/angular/build/src/builders/dev-server/vite/server.ts‎

Copy file name to clipboardExpand all lines: packages/angular/build/src/builders/dev-server/vite/server.ts
+19-11Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type { ComponentStyleRecord } from '../../../tools/vite/middlewares';
1313
import {
1414
ServerSsrMode,
1515
createAngularMemoryPlugin,
16+
createAngularServerSideSSLPlugin,
1617
createAngularSetupMiddlewaresPlugin,
1718
createAngularSsrTransformPlugin,
1819
createRemoveIdPrefixPlugin,
@@ -207,16 +208,19 @@ export async function setupServer(
207208
preTransformRequests,
208209
cacheDir,
209210
),
210-
ssr: createSsrConfig(
211-
externalMetadata,
212-
serverOptions,
213-
prebundleTransformer,
214-
zoneless,
215-
target,
216-
prebundleLoaderExtensions,
217-
thirdPartySourcemaps,
218-
define,
219-
),
211+
ssr:
212+
ssrMode === ServerSsrMode.NoSsr
213+
? undefined
214+
: createSsrConfig(
215+
externalMetadata,
216+
serverOptions,
217+
prebundleTransformer,
218+
zoneless,
219+
target,
220+
prebundleLoaderExtensions,
221+
thirdPartySourcemaps,
222+
define,
223+
),
220224
plugins: [
221225
createAngularSetupMiddlewaresPlugin({
222226
outputFiles,
@@ -258,11 +262,15 @@ export async function setupServer(
258262
};
259263

260264
if (serverOptions.ssl) {
265+
configuration.plugins ??= [];
261266
if (!serverOptions.sslCert || !serverOptions.sslKey) {
262267
const { default: basicSslPlugin } = await import('@vitejs/plugin-basic-ssl');
263-
configuration.plugins ??= [];
264268
configuration.plugins.push(basicSslPlugin());
265269
}
270+
271+
if (ssrMode !== ServerSsrMode.NoSsr) {
272+
configuration.plugins?.push(createAngularServerSideSSLPlugin());
273+
}
266274
}
267275

268276
return configuration;
Collapse file

‎packages/angular/build/src/tools/vite/plugins/index.ts‎

Copy file name to clipboardExpand all lines: packages/angular/build/src/tools/vite/plugins/index.ts
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ export { createAngularMemoryPlugin } from './angular-memory-plugin';
1010
export { createRemoveIdPrefixPlugin } from './id-prefix-plugin';
1111
export { createAngularSetupMiddlewaresPlugin, ServerSsrMode } from './setup-middlewares-plugin';
1212
export { createAngularSsrTransformPlugin } from './ssr-transform-plugin';
13+
export { createAngularServerSideSSLPlugin } from './ssr-ssl-plugin';
Collapse file
+64Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.dev/license
7+
*/
8+
9+
import type { Plugin } from 'vite';
10+
11+
export function createAngularServerSideSSLPlugin(): Plugin {
12+
return {
13+
name: 'angular-ssr-ssl-plugin',
14+
apply: 'serve',
15+
async configureServer({ config, httpServer }) {
16+
console.log('config server');
17+
const {
18+
ssr,
19+
server: { https },
20+
} = config;
21+
22+
if (!ssr || !https) {
23+
return;
24+
}
25+
26+
const { getGlobalDispatcher, setGlobalDispatcher, Agent } = await import('undici');
27+
const originalDispatcher = getGlobalDispatcher();
28+
29+
setGlobalDispatcher(
30+
new Agent({
31+
connect: {
32+
ca: [...getCerts(https.key), ...getCerts(https.cert)].join('\n'),
33+
},
34+
}),
35+
);
36+
37+
httpServer?.on('close', () => {
38+
console.log('setting original');
39+
setGlobalDispatcher(originalDispatcher);
40+
});
41+
},
42+
};
43+
}
44+
45+
function getCerts(
46+
items: string | Buffer | (string | Buffer | { pem: string | Buffer })[] | undefined,
47+
): string[] {
48+
if (!items) {
49+
return [];
50+
}
51+
52+
const certs: string[] = [];
53+
if (Array.isArray(items)) {
54+
for (const item of items) {
55+
const value = typeof item === 'string' ? item : item.toString('utf-8');
56+
certs.push(value.trim());
57+
}
58+
} else {
59+
const value = typeof items === 'string' ? items : items.toString('utf-8');
60+
certs.push(value.trim());
61+
}
62+
63+
return certs;
64+
}
Collapse file

‎packages/angular_devkit/build_angular/src/builders/dev-server/specs/ssl_spec.ts‎

Copy file name to clipboardExpand all lines: packages/angular_devkit/build_angular/src/builders/dev-server/specs/ssl_spec.ts
+5-13Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import { Architect, BuilderRun } from '@angular-devkit/architect';
1010
import { tags } from '@angular-devkit/core';
11-
import { Agent, getGlobalDispatcher, setGlobalDispatcher } from 'undici';
11+
import { Agent } from 'undici';
1212
import { createArchitect, host } from '../../../testing/test-utils';
1313
import { DevServerBuilderOutput } from '../index';
1414

@@ -35,20 +35,12 @@ describe('Dev Server Builder ssl', () => {
3535
expect(output.success).toBe(true);
3636
expect(output.baseUrl).toMatch(/^https:\/\/localhost:\d+\//);
3737

38-
// The self-signed certificate used by the dev server will cause fetch to fail
39-
// unless reject unauthorized is disabled.
40-
const originalDispatcher = getGlobalDispatcher();
41-
setGlobalDispatcher(
42-
new Agent({
38+
const response = await fetch(output.baseUrl, {
39+
dispatcher: new Agent({
4340
connect: { rejectUnauthorized: false },
4441
}),
45-
);
46-
try {
47-
const response = await fetch(output.baseUrl);
48-
expect(await response.text()).toContain('<title>HelloWorldApp</title>');
49-
} finally {
50-
setGlobalDispatcher(originalDispatcher);
51-
}
42+
});
43+
expect(await response.text()).toContain('<title>HelloWorldApp</title>');
5244
});
5345

5446
it('supports key and cert', async () => {
Collapse file

‎packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/ssl_spec.ts‎

Copy file name to clipboardExpand all lines: packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/ssl_spec.ts
+6-13Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import { Architect } from '@angular-devkit/architect';
1010
// eslint-disable-next-line import/no-extraneous-dependencies
1111
import * as browserSync from 'browser-sync';
12-
import { Agent, getGlobalDispatcher, setGlobalDispatcher } from 'undici';
12+
import { Agent } from 'undici';
1313
import { createArchitect, host } from '../../../testing/test-utils';
1414
import { SSRDevServerBuilderOutput } from '../index';
1515

@@ -85,20 +85,13 @@ describe('Serve SSR Builder', () => {
8585
expect(output.success).toBe(true);
8686
expect(output.baseUrl).toBe(`https://localhost:${output.port}`);
8787

88-
// The self-signed certificate used by the dev server will cause fetch to fail
89-
// unless reject unauthorized is disabled.
90-
const originalDispatcher = getGlobalDispatcher();
91-
setGlobalDispatcher(
92-
new Agent({
88+
const response = await fetch(`https://localhost:${output.port}/index.html`, {
89+
dispatcher: new Agent({
9390
connect: { rejectUnauthorized: false },
9491
}),
95-
);
96-
try {
97-
const response = await fetch(`https://localhost:${output.port}/index.html`);
98-
expect(await response.text()).toContain('<title>HelloWorldApp</title>');
99-
} finally {
100-
setGlobalDispatcher(originalDispatcher);
101-
}
92+
});
93+
94+
expect(await response.text()).toContain('<title>HelloWorldApp</title>');
10295

10396
await run.stop();
10497
});
Collapse file

‎pnpm-lock.yaml‎

Copy file name to clipboardExpand all lines: pnpm-lock.yaml
+5-6Lines changed: 5 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Collapse file

‎tests/legacy-cli/BUILD.bazel‎

Copy file name to clipboardExpand all lines: tests/legacy-cli/BUILD.bazel
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ e2e_suites(
6868
# Extra runtime deps due to bundling issues.
6969
# TODO: Clean this up.
7070
"//:node_modules/express",
71+
"//:node_modules/undici",
7172
],
7273
runner = ":runner_entrypoint",
7374
)

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.