From f6b7cd925dacf0ae34cb8e49b4deaf2e5c52ccd4 Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Tue, 17 Sep 2024 14:22:45 -0400 Subject: [PATCH] fix(@angular/build): support HTTP HEAD requests for virtual output files When using the development server, HTTP HEAD requests will now correctly respond for the virtual output files generated from the Angular build system. Previously Vite only handled GET requests for the files. While HEAD requests are not common in development workflows, it can be needed in more complex cases with additional servers/proxies/etc. during development. --- .../vite/middlewares/assets-middleware.ts | 6 +++++ .../e2e/tests/commands/serve/head-request.ts | 25 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 tests/legacy-cli/e2e/tests/commands/serve/head-request.ts diff --git a/packages/angular/build/src/tools/vite/middlewares/assets-middleware.ts b/packages/angular/build/src/tools/vite/middlewares/assets-middleware.ts index b282831210f9..4042dad9c216 100644 --- a/packages/angular/build/src/tools/vite/middlewares/assets-middleware.ts +++ b/packages/angular/build/src/tools/vite/middlewares/assets-middleware.ts @@ -63,6 +63,12 @@ export function createAngularAssetsMiddleware( return; } + // Support HTTP HEAD requests for the virtual output files from the Angular build + if (req.method === 'HEAD' && outputFiles.get(pathname)?.servable) { + // While a GET will also generate content, the rest of the response is equivalent + req.method = 'GET'; + } + // Resource files are handled directly. // Global stylesheets (CSS files) are currently considered resources to workaround // dev server sourcemap issues with stylesheets. diff --git a/tests/legacy-cli/e2e/tests/commands/serve/head-request.ts b/tests/legacy-cli/e2e/tests/commands/serve/head-request.ts new file mode 100644 index 000000000000..82ba370a0743 --- /dev/null +++ b/tests/legacy-cli/e2e/tests/commands/serve/head-request.ts @@ -0,0 +1,25 @@ +import { ngServe } from '../../../utils/project'; + +export default async function () { + const port = await ngServe(); + // HTML + await checkHeadForUrl(`http://localhost:${port}/index.html`); + // Generated JS + await checkHeadForUrl(`http://localhost:${port}/main.js`); + // Generated CSS + await checkHeadForUrl(`http://localhost:${port}/styles.css`); + // Configured asset + await checkHeadForUrl(`http://localhost:${port}/favicon.ico`); +} + +async function checkHeadForUrl(url: string): Promise { + const result = await fetch(url, { method: 'HEAD' }); + const content = await result.blob(); + + if (content.size !== 0) { + throw new Error(`Expected "size" to be "0" but got "${content.size}".`); + } + if (result.status !== 200) { + throw new Error(`Expected "status" to be "200" but got "${result.status}".`); + } +}