Skip to content

Commit cfe970c

Browse files
committed
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`. (cherry picked from commit 3379a13)
1 parent 405bfa3 commit cfe970c

2 files changed

Lines changed: 31 additions & 1 deletion

File tree

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ async function initBrowserSync(
268268
target: `localhost:${nodeServerPort}`,
269269
proxyOptions: {
270270
xfwd: true,
271+
changeOrigin: false,
271272
},
272273
proxyRes: [
273274
(proxyRes) => {
@@ -277,7 +278,7 @@ async function initBrowserSync(
277278
},
278279
],
279280
// proxyOptions is not in the typings
280-
} as ProxyOptions & { proxyOptions: { xfwd: boolean } },
281+
} as ProxyOptions & { proxyOptions: { xfwd: boolean; changeOrigin: boolean } },
281282
host,
282283
port: bsPort,
283284
ui: false,

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +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 { get } from 'node:http';
1213
import { createArchitect, host } from '../../../testing/test-utils';
1314

1415
describe('Serve SSR Builder - Works', () => {
@@ -95,4 +96,32 @@ describe('Serve SSR Builder - Works', () => {
9596
expect(output.success).toBe(true);
9697
expect(output.baseUrl).not.toContain('4200');
9798
});
99+
100+
it('rejects requests with a disallowed Host header', async () => {
101+
const run = await architect.scheduleTarget(target, { port: 0 });
102+
try {
103+
const output = await run.result;
104+
expect(output.success).toBeTrue();
105+
106+
const statusCode = await new Promise<number | undefined>((resolve, reject) => {
107+
const req = get(
108+
{
109+
hostname: 'localhost',
110+
port: output.port,
111+
path: '/',
112+
headers: { host: 'example.com' },
113+
},
114+
(res) => {
115+
res.resume();
116+
resolve(res.statusCode);
117+
},
118+
);
119+
req.on('error', reject);
120+
});
121+
122+
expect(statusCode).toBe(500);
123+
} finally {
124+
await run.stop();
125+
}
126+
});
98127
});

0 commit comments

Comments
 (0)