diff --git a/packages/schematics/angular/migrations/trust-proxy-headers/migration.ts b/packages/schematics/angular/migrations/trust-proxy-headers/migration.ts index 695992901b66..a6136d672dfa 100644 --- a/packages/schematics/angular/migrations/trust-proxy-headers/migration.ts +++ b/packages/schematics/angular/migrations/trust-proxy-headers/migration.ts @@ -6,6 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ +import { isJsonObject } from '@angular-devkit/core'; import type { Rule } from '@angular-devkit/schematics'; import { Visitor, parseSync } from 'oxc-parser'; import { allTargetOptions, allWorkspaceTargets, getWorkspace } from '../../utility/workspace'; @@ -28,6 +29,13 @@ export default function (): Rule { if (typeof options?.['server'] === 'string') { serverFiles.add(options['server']); } + + // With the application builder, `server` is the server bootstrap file (`main.server.ts`). + // The app engine is created in the `ssr.entry` file (`server.ts`). + const ssr = options?.['ssr']; + if (ssr && isJsonObject(ssr) && typeof ssr['entry'] === 'string') { + serverFiles.add(ssr['entry']); + } } } diff --git a/packages/schematics/angular/migrations/trust-proxy-headers/migration_spec.ts b/packages/schematics/angular/migrations/trust-proxy-headers/migration_spec.ts index 5e997d74c1e9..970b228dcbf0 100644 --- a/packages/schematics/angular/migrations/trust-proxy-headers/migration_spec.ts +++ b/packages/schematics/angular/migrations/trust-proxy-headers/migration_spec.ts @@ -150,6 +150,46 @@ describe(`Migration to add trustProxyHeaders to server.ts`, () => { expect(content).toContain(`[trustProxyHeaders]: true`); }); + it(`should add trustProxyHeaders to the server file set in the 'ssr.entry' option`, async () => { + tree.overwrite( + '/angular.json', + JSON.stringify({ + version: 1, + projects: { + app: { + root: '', + sourceRoot: 'src', + projectType: 'application', + architect: { + build: { + options: { + server: 'src/main.server.ts', + outputMode: 'server', + ssr: { entry: 'src/server.ts' }, + }, + }, + }, + }, + }, + }), + ); + const mainServerContent = + `import { bootstrapApplication } from '@angular/platform-browser';\n` + + `export default (context) => bootstrapApplication(App, config, context);`; + tree.create('/src/main.server.ts', mainServerContent); + tree.create( + '/src/server.ts', + `import { AngularNodeAppEngine } from '@angular/ssr/node';\nconst angularApp = new AngularNodeAppEngine();`, + ); + + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + const content = newTree.readText('/src/server.ts'); + expect(content).toContain(`const angularApp = new AngularNodeAppEngine({`); + expect(content).toContain(TODO_COMMENT); + expect(content).toContain(`trustProxyHeaders: ['x-forwarded-host', 'x-forwarded-proto'],`); + expect(newTree.readText('/src/main.server.ts')).toBe(mainServerContent); + }); + it(`should skip files with parse errors without throwing`, async () => { const malformedContent = `import { AngularAppEngine } from '@angular/ssr';\nconst angularApp = new AngularAppEngine(;`; tree.create('/server.ts', malformedContent);