Fix .html.astro file routing in dev (#5346)

* Fix .html.astro file routing in dev

* Fix error

* Add comment
This commit is contained in:
Bjorn Lu 2022-11-12 00:01:53 +08:00 committed by GitHub
parent c01092dd09
commit f3181b5adf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 63 additions and 9 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Fix .html.astro file routing in dev

View file

@ -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);

View file

@ -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,
};

View file

@ -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')
});
});
});

View file

@ -0,0 +1,6 @@
---
export function getStaticPaths() {
return [{ params: { slug: '1' } }];
}
---
<h1>none: {Astro.params.slug}</h1>

View file

@ -0,0 +1,6 @@
---
export function getStaticPaths() {
return [{ params: { slug: '1' } }];
}
---
<h1>html: {Astro.params.slug}</h1>