From 07e21edcecfed65a442f8e24f7c402520eed4ecb Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Tue, 6 Oct 2026 08:31:16 +0000 Subject: [PATCH 1/2] fix(@angular-devkit/build-angular): preserve Host header when proxying in ssr-dev-server Configure `browser-sync` with `changeOrigin: false` in `ssr-dev-server` so that the incoming `Host` header is preserved when proxying requests to the Node SSR server rather than being rewritten to `localhost`. --- .../src/builders/ssr-dev-server/index.ts | 3 ++- .../ssr-dev-server/specs/works_spec.ts | 26 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/index.ts b/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/index.ts index 003eb693bb56..e3a58234892c 100644 --- a/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/index.ts +++ b/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/index.ts @@ -268,6 +268,7 @@ async function initBrowserSync( target: `localhost:${nodeServerPort}`, proxyOptions: { xfwd: true, + changeOrigin: false, }, proxyRes: [ (proxyRes) => { @@ -277,7 +278,7 @@ async function initBrowserSync( }, ], // proxyOptions is not in the typings - } as ProxyOptions & { proxyOptions: { xfwd: boolean } }, + } as ProxyOptions & { proxyOptions: { xfwd: boolean; changeOrigin: boolean } }, host, port: bsPort, ui: false, diff --git a/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/works_spec.ts b/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/works_spec.ts index 92324fa34526..169527ace0fa 100644 --- a/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/works_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/works_spec.ts @@ -9,6 +9,7 @@ import { Architect } from '@angular-devkit/architect'; // eslint-disable-next-line import/no-extraneous-dependencies import * as browserSync from 'browser-sync'; +import { get } from 'node:http'; import { createArchitect, host } from '../../../testing/test-utils'; describe('Serve SSR Builder - Works', () => { @@ -95,4 +96,29 @@ describe('Serve SSR Builder - Works', () => { expect(output.success).toBe(true); expect(output.baseUrl).not.toContain('4200'); }); + + it('rejects requests with a disallowed Host header', async () => { + const run = await architect.scheduleTarget(target, { port: 0 }); + const output = await run.result; + expect(output.success).toBeTrue(); + + const statusCode = await new Promise((resolve, reject) => { + const req = get( + { + hostname: 'localhost', + port: output.port, + path: '/', + headers: { host: 'example.com' }, + }, + (res) => { + res.resume(); + resolve(res.statusCode); + }, + ); + req.on('error', reject); + }); + + await run.stop(); + expect(statusCode).toBe(500); + }); }); From f62620ae119907663373aed1c403f25b37648e03 Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Tue, 6 Oct 2026 08:43:04 +0000 Subject: [PATCH 2/2] fixup! fix(@angular-devkit/build-angular): preserve Host header when proxying in ssr-dev-server --- .../ssr-dev-server/specs/works_spec.ts | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/works_spec.ts b/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/works_spec.ts index 169527ace0fa..4b2e6d980527 100644 --- a/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/works_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/works_spec.ts @@ -99,26 +99,29 @@ describe('Serve SSR Builder - Works', () => { it('rejects requests with a disallowed Host header', async () => { const run = await architect.scheduleTarget(target, { port: 0 }); - const output = await run.result; - expect(output.success).toBeTrue(); - - const statusCode = await new Promise((resolve, reject) => { - const req = get( - { - hostname: 'localhost', - port: output.port, - path: '/', - headers: { host: 'example.com' }, - }, - (res) => { - res.resume(); - resolve(res.statusCode); - }, - ); - req.on('error', reject); - }); - - await run.stop(); - expect(statusCode).toBe(500); + try { + const output = await run.result; + expect(output.success).toBeTrue(); + + const statusCode = await new Promise((resolve, reject) => { + const req = get( + { + hostname: 'localhost', + port: output.port, + path: '/', + headers: { host: 'example.com' }, + }, + (res) => { + res.resume(); + resolve(res.statusCode); + }, + ); + req.on('error', reject); + }); + + expect(statusCode).toBe(500); + } finally { + await run.stop(); + } }); });