Skip to content

Commit 47075be

Browse files
MeAkibclydin
authored andcommitted
fix(@angular/build): resolve dev-server sslKey and sslCert relative to the workspace root (#34399)
The Vite-based dev server read `sslKey` and `sslCert` relative to the current working directory, so serving failed with `ENOENT` when `ng serve` ran from a subdirectory of the workspace and the paths in `angular.json` were relative. Resolve both paths against the workspace root, as the webpack dev server already does. The new dev-server `ssl` spec covers relative paths. It fails with `ENOENT` without this change. PR Close #34399
1 parent db6af23 commit 47075be

2 files changed

Lines changed: 86 additions & 2 deletions

File tree

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,8 @@ export async function normalizeOptions(
142142
proxyConfig,
143143
servePath,
144144
ssl,
145-
sslCert,
146-
sslKey,
145+
sslCert: sslCert && path.resolve(workspaceRoot, sslCert),
146+
sslKey: sslKey && path.resolve(workspaceRoot, sslKey),
147147
// Prebundling defaults to true but requires caching to function
148148
prebundle: cacheOptions.enabled && !optimization.scripts && prebundle,
149149
inspect,
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
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 assert from 'node:assert';
10+
import { mkdtemp, writeFile } from 'node:fs/promises';
11+
import { join } from 'node:path';
12+
import { executeDevServer } from '../../index';
13+
import { describeServeBuilder } from '../jasmine-helpers';
14+
import { BASE_OPTIONS, DEV_SERVER_BUILDER_INFO } from '../setup';
15+
16+
const SSL_KEY = `-----BEGIN PRIVATE KEY-----
17+
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgEpythQjrJo9bm8GM
18+
LFacGutCqc/XxDZ3dDkSMYZYZ2ehRANCAARvwtZ3OwP1uLhrcLp7nemvaWqkA+FN
19+
NDjOA3OZKhyVHYog1jNTawJJjwk66upbXGFL8622yU1INWbZFxvrSANl
20+
-----END PRIVATE KEY-----
21+
`;
22+
23+
const SSL_CERT = `-----BEGIN CERTIFICATE-----
24+
MIIBfzCCASWgAwIBAgIUUoRhwzxAE3y5nrOW8de+cJEIVvQwCgYIKoZIzj0EAwIw
25+
FDESMBAGA1UEAwwJbG9jYWxob3N0MCAXDTI2MTAxOTA4NTUyNVoYDzIxMjYwOTI1
26+
MDg1NTI1WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwWTATBgcqhkjOPQIBBggqhkjO
27+
PQMBBwNCAARvwtZ3OwP1uLhrcLp7nemvaWqkA+FNNDjOA3OZKhyVHYog1jNTawJJ
28+
jwk66upbXGFL8622yU1INWbZFxvrSANlo1MwUTAdBgNVHQ4EFgQUWyqB1QeFcs6L
29+
LL7Utsybm6+XFvIwHwYDVR0jBBgwFoAUWyqB1QeFcs6LLL7Utsybm6+XFvIwDwYD
30+
VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiBazry25W+Qewb/WzadhmdY
31+
YDGdshNZCk0g0DI3ctNjlgIhAKm2X8pmqdkM38Yh8QDN0cHBsAcDfRYffDnjJ3tP
32+
dpnU
33+
-----END CERTIFICATE-----
34+
`;
35+
36+
describeServeBuilder(executeDevServer, DEV_SERVER_BUILDER_INFO, (harness, setupTarget) => {
37+
describe('option: "ssl"', () => {
38+
beforeEach(async () => {
39+
setupTarget(harness);
40+
41+
// Application code is not needed for these tests
42+
await harness.writeFile('src/main.ts', '');
43+
});
44+
45+
it('resolves "sslKey" and "sslCert" relative to the workspace root', async () => {
46+
await harness.writeFile('ssl/server.key', SSL_KEY);
47+
await harness.writeFile('ssl/server.crt', SSL_CERT);
48+
49+
harness.useTarget('serve', {
50+
...BASE_OPTIONS,
51+
ssl: true,
52+
sslKey: 'ssl/server.key',
53+
sslCert: 'ssl/server.crt',
54+
});
55+
56+
const { result } = await harness.executeOnce();
57+
58+
expect(result?.success).toBeTrue();
59+
expect(result?.baseUrl).toMatch(/^https:\/\/[^/]+:\d+\//);
60+
});
61+
62+
it('supports absolute "sslKey" and "sslCert" paths outside the workspace', async () => {
63+
const baseTmpDir = process.env['TEST_TMPDIR'];
64+
assert(baseTmpDir, 'TEST_TMPDIR is not set');
65+
const certsDir = await mkdtemp(join(baseTmpDir, 'angular-cli-ssl-'));
66+
const sslKey = join(certsDir, 'server.key');
67+
const sslCert = join(certsDir, 'server.crt');
68+
await writeFile(sslKey, SSL_KEY);
69+
await writeFile(sslCert, SSL_CERT);
70+
71+
harness.useTarget('serve', {
72+
...BASE_OPTIONS,
73+
ssl: true,
74+
sslKey,
75+
sslCert,
76+
});
77+
78+
const { result } = await harness.executeOnce();
79+
80+
expect(result?.success).toBeTrue();
81+
expect(result?.baseUrl).toMatch(/^https:\/\/[^/]+:\d+\//);
82+
});
83+
});
84+
});

0 commit comments

Comments
 (0)