From 23c0980ae5d32c29c0769560b8a89940ce1fedd9 Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Mon, 27 Apr 2026 12:33:43 +0000 Subject: [PATCH] fix(@angular/ssr): add support for configuring trusted proxy headers via environment variable Adds support for configuring trusted proxy headers via the `NG_TRUST_PROXY_HEADERS` environment variable in `AngularNodeAppEngine`. This allows users to specify which proxy headers (such as `X-Forwarded-Host`) should be trusted when running the server-side application behind a reverse proxy, without needing to modify the application code. The environment variable accepts a comma-separated list of header names. If the `NG_TRUST_PROXY_HEADERS` environment variable is set and contains non-empty values, it will take precedence over the `trustProxyHeaders` option provided programmatically in the `AngularNodeAppEngine` constructor options. --- packages/angular/ssr/node/src/app-engine.ts | 13 +++++--- .../node/src/common-engine/common-engine.ts | 5 +-- .../ssr/node/src/environment-options.ts | 31 +++++++++++++------ 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/packages/angular/ssr/node/src/app-engine.ts b/packages/angular/ssr/node/src/app-engine.ts index 986b4142a64f..b947107a3c5a 100644 --- a/packages/angular/ssr/node/src/app-engine.ts +++ b/packages/angular/ssr/node/src/app-engine.ts @@ -10,7 +10,7 @@ import { AngularAppEngine } from '@angular/ssr'; import type { IncomingMessage } from 'node:http'; import type { Http2ServerRequest } from 'node:http2'; import { AngularAppEngineOptions } from '../../src/app-engine'; -import { getAllowedHostsFromEnv } from './environment-options'; +import { getAllowedHostsFromEnv, getTrustProxyHeadersFromEnv } from './environment-options'; import { attachNodeGlobalErrorHandlers } from './errors'; import { createWebRequestFromNodeRequest } from './request'; @@ -36,11 +36,14 @@ export class AngularNodeAppEngine { * @param options Options for the Angular Node.js server application engine. */ constructor(options?: AngularNodeAppEngineOptions) { - this.angularAppEngine = new AngularAppEngine({ + const appEngineOptions: AngularAppEngineOptions = { ...options, - allowedHosts: [...getAllowedHostsFromEnv(), ...(options?.allowedHosts ?? [])], - }); - this.trustProxyHeaders = options?.trustProxyHeaders; + allowedHosts: getAllowedHostsFromEnv() ?? options?.allowedHosts, + trustProxyHeaders: getTrustProxyHeadersFromEnv() ?? options?.trustProxyHeaders, + }; + + this.angularAppEngine = new AngularAppEngine(appEngineOptions); + this.trustProxyHeaders = appEngineOptions.trustProxyHeaders; attachNodeGlobalErrorHandlers(); } diff --git a/packages/angular/ssr/node/src/common-engine/common-engine.ts b/packages/angular/ssr/node/src/common-engine/common-engine.ts index b44c2c5255ca..c7567741958f 100644 --- a/packages/angular/ssr/node/src/common-engine/common-engine.ts +++ b/packages/angular/ssr/node/src/common-engine/common-engine.ts @@ -72,10 +72,7 @@ export class CommonEngine { private readonly allowedHosts: ReadonlySet; constructor(private options?: CommonEngineOptions) { - this.allowedHosts = new Set([ - ...getAllowedHostsFromEnv(), - ...(this.options?.allowedHosts ?? []), - ]); + this.allowedHosts = new Set(getAllowedHostsFromEnv() ?? this.options?.allowedHosts ?? []); attachNodeGlobalErrorHandlers(); } diff --git a/packages/angular/ssr/node/src/environment-options.ts b/packages/angular/ssr/node/src/environment-options.ts index b18dcd08ebe6..2b7ee7d9040b 100644 --- a/packages/angular/ssr/node/src/environment-options.ts +++ b/packages/angular/ssr/node/src/environment-options.ts @@ -10,20 +10,31 @@ * Retrieves the list of allowed hosts from the environment variable `NG_ALLOWED_HOSTS`. * @returns An array of allowed hosts. */ -export function getAllowedHostsFromEnv(): ReadonlyArray { - const allowedHosts: string[] = []; - const envNgAllowedHosts = process.env['NG_ALLOWED_HOSTS']; - if (!envNgAllowedHosts) { - return allowedHosts; +export function getAllowedHostsFromEnv(): ReadonlyArray | undefined { + return getArrayFromEnv('NG_ALLOWED_HOSTS'); +} + +/** + * Retrieves the list of trusted proxy headers from the environment variable `NG_TRUST_PROXY_HEADERS`. + * @returns An array of trusted proxy headers. + */ +export function getTrustProxyHeadersFromEnv(): ReadonlyArray | undefined { + return getArrayFromEnv('NG_TRUST_PROXY_HEADERS'); +} + +function getArrayFromEnv(envName: string): ReadonlyArray | undefined { + const envValue = process.env[envName]; + if (!envValue) { + return undefined; } - const hosts = envNgAllowedHosts.split(','); - for (const host of hosts) { - const trimmed = host.trim(); + const values: string[] = []; + for (const value of envValue.split(',')) { + const trimmed = value.trim(); if (trimmed.length > 0) { - allowedHosts.push(trimmed); + values.push(trimmed); } } - return allowedHosts; + return values; }