From 13a3e430da894fee87e4279f51b166f657b29b3f Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Wed, 18 Sep 2024 21:24:30 -0400 Subject: [PATCH] fix(@angular/build): allow missing HTML file request to fallback to index If a HTTP request is made to the development server that explicitly requests an HTML file (i.e., `/abc.html`), the development server will now attempt to fallback to the root `index.html` file if the requested HTML file does not exist. Since this may indicate a defect or other application misconfiguration such as a missing asset, a warning will also be issued in the console during development to notify the developer that something may be wrong. --- .../middlewares/html-fallback-middleware.ts | 34 +++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/packages/angular/build/src/tools/vite/middlewares/html-fallback-middleware.ts b/packages/angular/build/src/tools/vite/middlewares/html-fallback-middleware.ts index 2dda2da36a0d..395368be0c00 100644 --- a/packages/angular/build/src/tools/vite/middlewares/html-fallback-middleware.ts +++ b/packages/angular/build/src/tools/vite/middlewares/html-fallback-middleware.ts @@ -10,6 +10,8 @@ import type { ServerResponse } from 'node:http'; import type { Connect } from 'vite'; import { lookupMimeTypeFromRequest } from '../utils'; +const ALLOWED_FALLBACK_METHODS = Object.freeze(['GET', 'HEAD']); + export function angularHtmlFallbackMiddleware( req: Connect.IncomingMessage, _res: ServerResponse, @@ -17,13 +19,33 @@ export function angularHtmlFallbackMiddleware( ): void { // Similar to how it is handled in vite // https://github.com/vitejs/vite/blob/main/packages/vite/src/node/server/middlewares/htmlFallback.ts#L15C19-L15C45 + if (!req.method || !ALLOWED_FALLBACK_METHODS.includes(req.method)) { + // No fallback for unsupported request methods + next(); + + return; + } + + if (req.url) { + const mimeType = lookupMimeTypeFromRequest(req.url); + if (mimeType === 'text/html' || mimeType === 'application/xhtml+xml') { + // eslint-disable-next-line no-console + console.warn( + `Request for HTML file "${req.url}" was received but no asset found. Asset may be missing from build.`, + ); + } else if (mimeType) { + // No fallback for request of asset-like files + next(); + + return; + } + } + if ( - (req.method === 'GET' || req.method === 'HEAD') && - (!req.url || !lookupMimeTypeFromRequest(req.url)) && - (!req.headers.accept || - req.headers.accept.includes('text/html') || - req.headers.accept.includes('text/*') || - req.headers.accept.includes('*/*')) + !req.headers.accept || + req.headers.accept.includes('text/html') || + req.headers.accept.includes('text/*') || + req.headers.accept.includes('*/*') ) { req.url = '/index.html'; }