mirror of
https://github.com/withastro/astro.git
synced 2025-02-17 22:44:24 -05:00
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 { config } = settings;
|
||||||
const origin = `${moduleLoader.isHttps() ? 'https' : 'http'}://${req.headers.host}`;
|
const origin = `${moduleLoader.isHttps() ? 'https' : 'http'}://${req.headers.host}`;
|
||||||
const buildingToSSR = config.output === 'server';
|
const buildingToSSR = config.output === 'server';
|
||||||
// Ignore `.html` extensions and `index.html` in request URLS to ensure that
|
const url = new URL(origin + req.url);
|
||||||
// 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 pathname = decodeURI(url.pathname);
|
const pathname = decodeURI(url.pathname);
|
||||||
|
|
||||||
// Add config.base back to url before passing it to SSR
|
// Add config.base back to url before passing it to SSR
|
||||||
|
@ -60,8 +57,18 @@ export async function handleRequest(
|
||||||
pathname,
|
pathname,
|
||||||
async run() {
|
async run() {
|
||||||
const matchedRoute = await matchRoute(pathname, env, manifest);
|
const matchedRoute = await matchRoute(pathname, env, manifest);
|
||||||
|
const resolvedPathname = matchedRoute?.resolvedPathname ?? pathname;
|
||||||
return await handleRoute(matchedRoute, url, pathname, body, origin, env, manifest, req, res);
|
return await handleRoute(
|
||||||
|
matchedRoute,
|
||||||
|
url,
|
||||||
|
resolvedPathname,
|
||||||
|
body,
|
||||||
|
origin,
|
||||||
|
env,
|
||||||
|
manifest,
|
||||||
|
req,
|
||||||
|
res
|
||||||
|
);
|
||||||
},
|
},
|
||||||
onError(_err) {
|
onError(_err) {
|
||||||
const err = createSafeError(_err);
|
const err = createSafeError(_err);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import type http from 'http';
|
import type http from 'http';
|
||||||
import mime from 'mime';
|
import mime from 'mime';
|
||||||
import type { AstroSettings, ManifestData } from '../@types/astro';
|
import type { AstroSettings, ComponentInstance, ManifestData, RouteData } from '../@types/astro';
|
||||||
import { DevelopmentEnvironment, SSROptions } from '../core/render/dev/index';
|
import { ComponentPreload, DevelopmentEnvironment, SSROptions } from '../core/render/dev/index';
|
||||||
|
|
||||||
import { attachToResponse } from '../core/cookies/index.js';
|
import { attachToResponse } from '../core/cookies/index.js';
|
||||||
import { call as callEndpoint } from '../core/endpoint/dev/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
|
? R
|
||||||
: any;
|
: any;
|
||||||
|
|
||||||
|
interface MatchedRoute {
|
||||||
|
route: RouteData;
|
||||||
|
filePath: URL;
|
||||||
|
resolvedPathname: string;
|
||||||
|
preloadedComponent: ComponentPreload;
|
||||||
|
mod: ComponentInstance;
|
||||||
|
}
|
||||||
|
|
||||||
function getCustom404Route({ config }: AstroSettings, manifest: ManifestData) {
|
function getCustom404Route({ config }: AstroSettings, manifest: ManifestData) {
|
||||||
// For Windows compat, use relative page paths to match the 404 route
|
// For Windows compat, use relative page paths to match the 404 route
|
||||||
const relPages = resolvePages(config).href.replace(config.root.href, '');
|
const relPages = resolvePages(config).href.replace(config.root.href, '');
|
||||||
|
@ -34,7 +42,7 @@ export async function matchRoute(
|
||||||
pathname: string,
|
pathname: string,
|
||||||
env: DevelopmentEnvironment,
|
env: DevelopmentEnvironment,
|
||||||
manifest: ManifestData
|
manifest: ManifestData
|
||||||
) {
|
): Promise<MatchedRoute | undefined> {
|
||||||
const { logging, settings, routeCache } = env;
|
const { logging, settings, routeCache } = env;
|
||||||
const matches = matchAllRoutes(pathname, manifest);
|
const matches = matchAllRoutes(pathname, manifest);
|
||||||
|
|
||||||
|
@ -57,12 +65,21 @@ export async function matchRoute(
|
||||||
return {
|
return {
|
||||||
route: maybeRoute,
|
route: maybeRoute,
|
||||||
filePath,
|
filePath,
|
||||||
|
resolvedPathname: pathname,
|
||||||
preloadedComponent,
|
preloadedComponent,
|
||||||
mod,
|
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) {
|
if (matches.length) {
|
||||||
const possibleRoutes = matches.flatMap((route) => route.component);
|
const possibleRoutes = matches.flatMap((route) => route.component);
|
||||||
|
|
||||||
|
@ -86,6 +103,7 @@ export async function matchRoute(
|
||||||
return {
|
return {
|
||||||
route: custom404,
|
route: custom404,
|
||||||
filePath,
|
filePath,
|
||||||
|
resolvedPathname: pathname,
|
||||||
preloadedComponent,
|
preloadedComponent,
|
||||||
mod,
|
mod,
|
||||||
};
|
};
|
||||||
|
|
|
@ -322,5 +322,17 @@ describe('Development Routing', () => {
|
||||||
const response = await fixture.fetch('/1');
|
const response = await fixture.fetch('/1');
|
||||||
expect(response.status).to.equal(200);
|
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…
Add table
Reference in a new issue