Skip to content

Commit d9a00e2

Browse files
committed
fix(@angular-devkit/build-angular): update vite to version 5.4.14
Version update from 5.1.8 to address advisory GHSA-vg6x-rcgg-rjx6 Vite version 5.4.12+, which is now used by the Angular CLI with the `application`/`browser-esbuild` builders, contains a potentially breaking change for some development setups. Examples of such setups include those that use reverse proxies or custom host names during development. The change within a patch release was made by Vite to address a security vulnerability. For projects that directly access the development server via `localhost`, no changes should be needed. However, some development setups may now need to adjust the `allowedHosts` development server option. This option can include an array of host names that are allowed to communicate with the development server. The option sets the corresponding Vite option within the Angular CLI. For more information on the option and its specific behavior, please see the Vite documentation located here: https://vite.dev/config/server-options.html#server-allowedhosts The following is an example of the configuration option allowing `example.com`: ``` "serve": { "builder": "@angular-devkit/build-angular:dev-server", "options": { "allowedHosts": ["example.com"] }, ```
1 parent 29c6b0d commit d9a00e2

File tree

7 files changed

+387
-57
lines changed

7 files changed

+387
-57
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@
210210
"undici": "6.11.1",
211211
"verdaccio": "5.29.2",
212212
"verdaccio-auth-memory": "^10.0.0",
213-
"vite": "5.1.8",
213+
"vite": "5.4.14",
214214
"watchpack": "2.4.0",
215215
"webpack": "5.94.0",
216216
"webpack-dev-middleware": "6.1.2",

packages/angular_devkit/build_angular/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
"tree-kill": "1.2.2",
6363
"tslib": "2.6.2",
6464
"undici": "6.11.1",
65-
"vite": "5.1.8",
65+
"vite": "5.4.14",
6666
"watchpack": "2.4.0",
6767
"webpack": "5.94.0",
6868
"webpack-dev-middleware": "6.1.2",

packages/angular_devkit/build_angular/src/builders/dev-server/schema.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373
},
7474
"allowedHosts": {
7575
"type": "array",
76-
"description": "List of hosts that are allowed to access the dev server. This option has no effect when using the 'application' or other esbuild-based builders.",
76+
"description": "List of hosts that are allowed to access the dev server.",
7777
"default": [],
7878
"items": {
7979
"type": "string"
@@ -85,7 +85,7 @@
8585
},
8686
"disableHostCheck": {
8787
"type": "boolean",
88-
"description": "Don't verify connected clients are part of allowed hosts. This option has no effect when using the 'application' or other esbuild-based builders.",
88+
"description": "Don't verify connected clients are part of allowed hosts.",
8989
"default": false
9090
},
9191
"hmr": {

packages/angular_devkit/build_angular/src/builders/dev-server/tests/execute-fetch.ts

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9+
import { IncomingMessage, RequestOptions, get } from 'node:http';
10+
import { text } from 'node:stream/consumers';
911
import { lastValueFrom, mergeMap, take, timeout } from 'rxjs';
10-
import { URL } from 'url';
1112
import {
1213
BuilderHarness,
1314
BuilderHarnessExecutionOptions,
@@ -41,3 +42,48 @@ export async function executeOnceAndFetch<T>(
4142
),
4243
);
4344
}
45+
46+
/**
47+
* Executes the builder and then immediately performs a GET request
48+
* via the Node.js `http` builtin module. This is useful for cases
49+
* where the `fetch` API is limited such as testing different `Host`
50+
* header values with the development server.
51+
* The `fetch` based alternative is preferred otherwise.
52+
*
53+
* @param harness A builder harness instance.
54+
* @param url The URL string to get.
55+
* @param options An options object.
56+
*/
57+
export async function executeOnceAndGet<T>(
58+
harness: BuilderHarness<T>,
59+
url: string,
60+
options?: Partial<BuilderHarnessExecutionOptions> & { request?: RequestOptions },
61+
): Promise<BuilderHarnessExecutionResult & { response?: IncomingMessage; content?: string }> {
62+
return lastValueFrom(
63+
harness.execute().pipe(
64+
timeout(30_000),
65+
mergeMap(async (executionResult) => {
66+
let response = undefined;
67+
let content = undefined;
68+
if (executionResult.result?.success) {
69+
let baseUrl = `${executionResult.result.baseUrl}`;
70+
baseUrl = baseUrl[baseUrl.length - 1] === '/' ? baseUrl : `${baseUrl}/`;
71+
const resolvedUrl = new URL(url, baseUrl);
72+
73+
response = await new Promise<IncomingMessage>((resolve) =>
74+
get(resolvedUrl, options?.request ?? {}, resolve),
75+
);
76+
77+
if (response.statusCode === 200) {
78+
content = await text(response);
79+
}
80+
81+
response.resume();
82+
}
83+
84+
return { ...executionResult, response, content };
85+
}),
86+
take(1),
87+
),
88+
);
89+
}

packages/angular_devkit/build_angular/src/builders/dev-server/tests/options/allowed-hosts_spec.ts

Lines changed: 31 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -7,65 +7,52 @@
77
*/
88

99
import { executeDevServer } from '../../index';
10-
import { executeOnceAndFetch } from '../execute-fetch';
10+
import { executeOnceAndGet } from '../execute-fetch';
1111
import { describeServeBuilder } from '../jasmine-helpers';
1212
import { BASE_OPTIONS, DEV_SERVER_BUILDER_INFO } from '../setup';
1313

1414
const FETCH_HEADERS = Object.freeze({ host: 'example.com' });
1515

16-
describeServeBuilder(
17-
executeDevServer,
18-
DEV_SERVER_BUILDER_INFO,
19-
(harness, setupTarget, isViteRun) => {
20-
// TODO(fix-vite): currently this is broken in vite.
21-
(isViteRun ? xdescribe : describe)('option: "allowedHosts"', () => {
22-
beforeEach(async () => {
23-
setupTarget(harness);
16+
describeServeBuilder(executeDevServer, DEV_SERVER_BUILDER_INFO, (harness, setupTarget) => {
17+
describe('option: "allowedHosts"', () => {
18+
beforeEach(async () => {
19+
setupTarget(harness);
2420

25-
// Application code is not needed for these tests
26-
await harness.writeFile('src/main.ts', '');
27-
});
28-
29-
it('does not allow an invalid host when option is not present', async () => {
30-
harness.useTarget('serve', {
31-
...BASE_OPTIONS,
32-
});
21+
// Application code is not needed for these tests
22+
await harness.writeFile('src/main.ts', '');
23+
});
3324

34-
const { result, response } = await executeOnceAndFetch(harness, '/', {
35-
request: { headers: FETCH_HEADERS },
36-
});
25+
it('does not allow an invalid host when option is not present', async () => {
26+
harness.useTarget('serve', { ...BASE_OPTIONS });
3727

38-
expect(result?.success).toBeTrue();
39-
expect(await response?.text()).toBe('Invalid Host header');
28+
const { result, response } = await executeOnceAndGet(harness, '/', {
29+
request: { headers: FETCH_HEADERS },
4030
});
4131

42-
it('does not allow an invalid host when option is an empty array', async () => {
43-
harness.useTarget('serve', {
44-
...BASE_OPTIONS,
45-
allowedHosts: [],
46-
});
32+
expect(result?.success).toBeTrue();
33+
expect(response?.statusCode).toBe(403);
34+
});
4735

48-
const { result, response } = await executeOnceAndFetch(harness, '/', {
49-
request: { headers: FETCH_HEADERS },
50-
});
36+
it('does not allow an invalid host when option is an empty array', async () => {
37+
harness.useTarget('serve', { ...BASE_OPTIONS, allowedHosts: [] });
5138

52-
expect(result?.success).toBeTrue();
53-
expect(await response?.text()).toBe('Invalid Host header');
39+
const { result, response } = await executeOnceAndGet(harness, '/', {
40+
request: { headers: FETCH_HEADERS },
5441
});
5542

56-
it('allows a host when specified in the option', async () => {
57-
harness.useTarget('serve', {
58-
...BASE_OPTIONS,
59-
allowedHosts: ['example.com'],
60-
});
43+
expect(result?.success).toBeTrue();
44+
expect(response?.statusCode).toBe(403);
45+
});
6146

62-
const { result, response } = await executeOnceAndFetch(harness, '/', {
63-
request: { headers: FETCH_HEADERS },
64-
});
47+
it('allows a host when specified in the option', async () => {
48+
harness.useTarget('serve', { ...BASE_OPTIONS, allowedHosts: ['example.com'] });
6549

66-
expect(result?.success).toBeTrue();
67-
expect(await response?.text()).toContain('<title>');
50+
const { result, content } = await executeOnceAndGet(harness, '/', {
51+
request: { headers: FETCH_HEADERS },
6852
});
53+
54+
expect(result?.success).toBeTrue();
55+
expect(content).toContain('<title>');
6956
});
70-
},
71-
);
57+
});
58+
});

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,7 @@ export async function setupServer(
485485
strictPort: true,
486486
host: serverOptions.host,
487487
open: serverOptions.open,
488+
allowedHosts: serverOptions.allowedHosts,
488489
headers: serverOptions.headers,
489490
proxy,
490491
cors: {

0 commit comments

Comments
 (0)