Repository navigation
fix(@angular/build): allow allowed-hosts CLI option for dev-server #34595
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| /** | ||
| * @license | ||
| * Copyright Google LLC All Rights Reserved. | ||
| * | ||
| * Use of this source code is governed by an MIT-style license that can be | ||
| * found in the LICENSE file at https://angular.dev/license | ||
| */ | ||
|
|
||
| import { executeDevServer } from '../../index'; | ||
| import { executeOnceAndGet } from '../execute-fetch'; | ||
| import { describeServeBuilder } from '../jasmine-helpers'; | ||
| import { BASE_OPTIONS, DEV_SERVER_BUILDER_INFO } from '../setup'; | ||
| import { text } from 'node:stream/consumers'; | ||
|
|
||
| const FETCH_HEADERS = Object.freeze({ Host: 'example.com' }); | ||
|
|
||
| describeServeBuilder(executeDevServer, DEV_SERVER_BUILDER_INFO, (harness, setupTarget) => { | ||
| describe('option: "disableHostCheck"', () => { | ||
| beforeEach(async () => { | ||
| setupTarget(harness); | ||
|
|
||
| // Application code is not needed for these tests | ||
| await harness.writeFile('src/main.ts', ''); | ||
| }); | ||
|
|
||
| it('does not allow an invalid host when option is not present', async () => { | ||
| harness.useTarget('serve', { | ||
| ...BASE_OPTIONS, | ||
| }); | ||
|
|
||
| const { result, response } = await executeOnceAndGet(harness, '/', { | ||
| request: { headers: FETCH_HEADERS }, | ||
| }); | ||
|
|
||
| expect(result?.success).toBeTrue(); | ||
| expect(response?.statusCode).toBe(403); | ||
| expect(response && (await text(response))).toContain('angular.json'); | ||
| }); | ||
|
|
||
| it('does not allow an invalid host when option is false', async () => { | ||
| harness.useTarget('serve', { | ||
| ...BASE_OPTIONS, | ||
| disableHostCheck: false, | ||
| }); | ||
|
|
||
| const { result, response } = await executeOnceAndGet(harness, '/', { | ||
| request: { headers: FETCH_HEADERS }, | ||
| }); | ||
|
|
||
| expect(result?.success).toBeTrue(); | ||
| expect(response?.statusCode).toBe(403); | ||
| expect(response && (await text(response))).toContain('angular.json'); | ||
| }); | ||
|
|
||
| it('allows a host when option is true', async () => { | ||
| harness.useTarget('serve', { | ||
| ...BASE_OPTIONS, | ||
| disableHostCheck: true, | ||
| }); | ||
|
|
||
| const { result, content } = await executeOnceAndGet(harness, '/', { | ||
| request: { headers: FETCH_HEADERS }, | ||
| }); | ||
|
|
||
| expect(result?.success).toBeTrue(); | ||
| expect(content).toContain('<title>'); | ||
| }); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,8 @@ | |
| */ | ||
|
|
||
| import { JsonObject, schema } from '@angular-devkit/core'; | ||
| import { readFileSync } from 'node:fs'; | ||
| import path from 'node:path'; | ||
| import type { Argv } from 'yargs'; | ||
| import yargs from 'yargs'; | ||
|
|
||
|
|
@@ -389,4 +391,42 @@ describe('parseJsonSchemaToOptions', () => { | |
| ]); | ||
| }); | ||
| }); | ||
|
|
||
| describe('@angular/build dev-server schema', () => { | ||
| const devServerSchemaPath = path.join( | ||
| import.meta.dirname, | ||
| '../../../../build/src/builders/dev-server/schema.json', | ||
| ); | ||
|
Comment on lines
+396
to
+399
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using const devServerSchemaPath = fileURLToPath(
new URL('../../../../build/src/builders/dev-server/schema.json', import.meta.url),
); |
||
|
|
||
| const parse = async (args: string[]) => { | ||
| return localYargs.parseAsync(args); | ||
| }; | ||
|
|
||
| let localYargs: Argv<unknown>; | ||
|
|
||
| beforeEach(async () => { | ||
| localYargs = yargs().exitProcess(false).strict().fail(false).wrap(1_000); | ||
|
|
||
| const devServerSchema = JSON.parse(readFileSync(devServerSchemaPath, 'utf8')) as JsonObject; | ||
| const registry = new schema.CoreSchemaRegistry(); | ||
| const options = await parseJsonSchemaToOptions(registry, devServerSchema, false); | ||
| addSchemaOptionsToCommand(localYargs, options, true); | ||
| }); | ||
|
|
||
| it('parses --allowed-hosts with host names', async () => { | ||
| expect(await parse(['--allowed-hosts', 'example.com'])).toEqual( | ||
| jasmine.objectContaining({ | ||
| allowedHosts: ['example.com'], | ||
| }), | ||
| ); | ||
| }); | ||
|
|
||
| it('parses --disable-host-check', async () => { | ||
| expect(await parse(['--disable-host-check'])).toEqual( | ||
| jasmine.objectContaining({ | ||
| disableHostCheck: true, | ||
| }), | ||
| ); | ||
| }); | ||
| }); | ||
| }); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Import
fileURLToPathfromnode:urlto resolve the schema path robustly usingimport.meta.url.