Fix .html.astro file routing in dev (#5346)
* Fix .html.astro file routing in dev * Fix error * Add comment
This commit is contained in:
parent
c01092dd09
commit
f3181b5adf
6 changed files with 63 additions and 9 deletions
5
.changeset/chatty-kiwis-fail.md
Normal file
5
.changeset/chatty-kiwis-fail.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Fix .html.astro file routing in dev
|
|
@ -23,10 +23,7 @@ export async function handleRequest(
|
|||
const { config } = settings;
|
||||
const origin = `${moduleLoader.isHttps() ? 'https' : 'http'}://${req.headers.host}`;
|
||||
const buildingToSSR = config.output === 'server';
|
||||
// Ignore `.html` extensions and `index.html` in request URLS to ensure that
|
||||
// routing behavior matches production builds. This supports both file and directory
|
||||
// build formats, and is necessary based on how the manifest tracks build targets.
|
||||
const url = new URL(origin + req.url?.replace(/(index)?\.html$/, ''));
|
||||
const url = new URL(origin + req.url);
|
||||
const pathname = decodeURI(url.pathname);
|
||||
|
||||
// Add config.base back to url before passing it to SSR
|
||||
|
@ -60,8 +57,18 @@ export async function handleRequest(
|
|||
pathname,
|
||||
async run() {
|
||||
const matchedRoute = await matchRoute(pathname, env, manifest);
|
||||
|
||||
return await handleRoute(matchedRoute, url, pathname, body, origin, env, manifest, req, res);
|
||||
const resolvedPathname = matchedRoute?.resolvedPathname ?? pathname;
|
||||
return await handleRoute(
|
||||
matchedRoute,
|
||||
url,
|
||||
resolvedPathname,
|
||||
body,
|
||||
origin,
|
||||
env,
|
||||
manifest,
|
||||
req,
|
||||
res
|
||||
);
|
||||
},
|
||||
onError(_err) {
|
||||
const err = createSafeError(_err);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type http from 'http';
|
||||
import mime from 'mime';
|
||||
import type { AstroSettings, ManifestData } from '../@types/astro';
|
||||
import { DevelopmentEnvironment, SSROptions } from '../core/render/dev/index';
|
||||
import type { AstroSettings, ComponentInstance, ManifestData, RouteData } from '../@types/astro';
|
||||
import { ComponentPreload, DevelopmentEnvironment, SSROptions } from '../core/render/dev/index';
|
||||
|
||||
import { attachToResponse } from '../core/cookies/index.js';
|
||||
import { call as callEndpoint } from '../core/endpoint/dev/index.js';
|
||||
|
@ -23,6 +23,14 @@ type AsyncReturnType<T extends (...args: any) => Promise<any>> = T extends (
|
|||
? R
|
||||
: any;
|
||||
|
||||
interface MatchedRoute {
|
||||
route: RouteData;
|
||||
filePath: URL;
|
||||
resolvedPathname: string;
|
||||
preloadedComponent: ComponentPreload;
|
||||
mod: ComponentInstance;
|
||||
}
|
||||
|
||||
function getCustom404Route({ config }: AstroSettings, manifest: ManifestData) {
|
||||
// For Windows compat, use relative page paths to match the 404 route
|
||||
const relPages = resolvePages(config).href.replace(config.root.href, '');
|
||||
|
@ -34,7 +42,7 @@ export async function matchRoute(
|
|||
pathname: string,
|
||||
env: DevelopmentEnvironment,
|
||||
manifest: ManifestData
|
||||
) {
|
||||
): Promise<MatchedRoute | undefined> {
|
||||
const { logging, settings, routeCache } = env;
|
||||
const matches = matchAllRoutes(pathname, manifest);
|
||||
|
||||
|
@ -57,12 +65,21 @@ export async function matchRoute(
|
|||
return {
|
||||
route: maybeRoute,
|
||||
filePath,
|
||||
resolvedPathname: pathname,
|
||||
preloadedComponent,
|
||||
mod,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Try without `.html` extensions or `index.html` in request URLs to mimic
|
||||
// routing behavior in production builds. This supports both file and directory
|
||||
// build formats, and is necessary based on how the manifest tracks build targets.
|
||||
const altPathname = pathname.replace(/(index)?\.html$/, '');
|
||||
if (altPathname !== pathname) {
|
||||
return await matchRoute(altPathname, env, manifest);
|
||||
}
|
||||
|
||||
if (matches.length) {
|
||||
const possibleRoutes = matches.flatMap((route) => route.component);
|
||||
|
||||
|
@ -86,6 +103,7 @@ export async function matchRoute(
|
|||
return {
|
||||
route: custom404,
|
||||
filePath,
|
||||
resolvedPathname: pathname,
|
||||
preloadedComponent,
|
||||
mod,
|
||||
};
|
||||
|
|
|
@ -322,5 +322,17 @@ describe('Development Routing', () => {
|
|||
const response = await fixture.fetch('/1');
|
||||
expect(response.status).to.equal(200);
|
||||
});
|
||||
|
||||
it('200 when loading /html-ext/1', async () => {
|
||||
const response = await fixture.fetch('/html-ext/1');
|
||||
expect(response.status).to.equal(200);
|
||||
expect(await response.text()).includes('none: 1')
|
||||
});
|
||||
|
||||
it('200 when loading /html-ext/1.html', async () => {
|
||||
const response = await fixture.fetch('/html-ext/1.html');
|
||||
expect(response.status).to.equal(200);
|
||||
expect(await response.text()).includes('html: 1')
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
6
packages/astro/test/fixtures/without-site-config/src/pages/html-ext/[slug].astro
vendored
Normal file
6
packages/astro/test/fixtures/without-site-config/src/pages/html-ext/[slug].astro
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
export function getStaticPaths() {
|
||||
return [{ params: { slug: '1' } }];
|
||||
}
|
||||
---
|
||||
<h1>none: {Astro.params.slug}</h1>
|
6
packages/astro/test/fixtures/without-site-config/src/pages/html-ext/[slug].html.astro
vendored
Normal file
6
packages/astro/test/fixtures/without-site-config/src/pages/html-ext/[slug].html.astro
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
export function getStaticPaths() {
|
||||
return [{ params: { slug: '1' } }];
|
||||
}
|
||||
---
|
||||
<h1>html: {Astro.params.slug}</h1>
|
Loading…
Reference in a new issue