mirror of
https://github.com/withastro/astro.git
synced 2025-01-20 22:12:38 -05:00
fix(i18n): render 404.astro
when i18n is enabled (#12525)
Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> Co-authored-by: delucis <357379+delucis@users.noreply.github.com> Co-authored-by: bluwy <34116392+bluwy@users.noreply.github.com>
This commit is contained in:
parent
8b0e36ca91
commit
cf0d8b08a0
6 changed files with 28 additions and 25 deletions
5
.changeset/hot-dingos-dress.md
Normal file
5
.changeset/hot-dingos-dress.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Fixes an issue where with `i18n` enabled, Astro couldn't render the `404.astro` component for non-existent routes.
|
|
@ -1,6 +1,6 @@
|
|||
import type { APIContext, MiddlewareHandler, SSRManifest } from '../@types/astro.js';
|
||||
import type { SSRManifestI18n } from '../core/app/types.js';
|
||||
import { ROUTE_TYPE_HEADER } from '../core/constants.js';
|
||||
import { REROUTE_DIRECTIVE_HEADER, ROUTE_TYPE_HEADER } from '../core/constants.js';
|
||||
import {
|
||||
type MiddlewarePayload,
|
||||
normalizeTheLocale,
|
||||
|
@ -65,6 +65,12 @@ export function createI18nMiddleware(
|
|||
return async (context, next) => {
|
||||
const response = await next();
|
||||
const type = response.headers.get(ROUTE_TYPE_HEADER);
|
||||
|
||||
// This is case where we are internally rendering a 404/500, so we need to bypass checks that were done already
|
||||
const isReroute = response.headers.get(REROUTE_DIRECTIVE_HEADER);
|
||||
if (isReroute === 'no' && typeof i18n.fallback === 'undefined') {
|
||||
return response;
|
||||
}
|
||||
// If the route we're processing is not a page, then we ignore it
|
||||
if (type !== 'page' && type !== 'fallback') {
|
||||
return response;
|
||||
|
|
|
@ -63,7 +63,6 @@ export async function handleRequest({
|
|||
url,
|
||||
pathname: resolvedPathname,
|
||||
body,
|
||||
origin,
|
||||
pipeline,
|
||||
manifestData,
|
||||
incomingRequest: incomingRequest,
|
||||
|
|
|
@ -127,7 +127,6 @@ type HandleRoute = {
|
|||
url: URL;
|
||||
pathname: string;
|
||||
body: ArrayBuffer | undefined;
|
||||
origin: string;
|
||||
manifestData: ManifestData;
|
||||
incomingRequest: http.IncomingMessage;
|
||||
incomingResponse: http.ServerResponse;
|
||||
|
@ -139,7 +138,6 @@ export async function handleRoute({
|
|||
url,
|
||||
pathname,
|
||||
body,
|
||||
origin,
|
||||
pipeline,
|
||||
manifestData,
|
||||
incomingRequest,
|
||||
|
@ -156,12 +154,10 @@ export async function handleRoute({
|
|||
let request: Request;
|
||||
let renderContext: RenderContext;
|
||||
let mod: ComponentInstance | undefined = undefined;
|
||||
let options: SSROptions | undefined = undefined;
|
||||
let route: RouteData;
|
||||
const middleware = (await loadMiddleware(loader)).onRequest;
|
||||
const locals = Reflect.get(incomingRequest, clientLocalsSymbol);
|
||||
|
||||
const filePath: URL | undefined = matchedRoute.filePath;
|
||||
const { preloadedComponent } = matchedRoute;
|
||||
route = matchedRoute.route;
|
||||
// Allows adapters to pass in locals in dev mode.
|
||||
|
@ -181,15 +177,6 @@ export async function handleRoute({
|
|||
if (value) incomingResponse.setHeader(name, value);
|
||||
}
|
||||
|
||||
options = {
|
||||
pipeline,
|
||||
filePath,
|
||||
preload: preloadedComponent,
|
||||
pathname,
|
||||
request,
|
||||
route,
|
||||
};
|
||||
|
||||
mod = preloadedComponent;
|
||||
|
||||
renderContext = await RenderContext.create({
|
||||
|
@ -248,18 +235,17 @@ export async function handleRoute({
|
|||
|
||||
if (statusCode === 404 && response.headers.get(REROUTE_DIRECTIVE_HEADER) !== 'no') {
|
||||
const fourOhFourRoute = await matchRoute('/404', manifestData, pipeline);
|
||||
if (options && options.route !== fourOhFourRoute?.route)
|
||||
return handleRoute({
|
||||
...options,
|
||||
matchedRoute: fourOhFourRoute,
|
||||
url: new URL(pathname, url),
|
||||
body,
|
||||
origin,
|
||||
if (fourOhFourRoute) {
|
||||
renderContext = await RenderContext.create({
|
||||
locals,
|
||||
pipeline,
|
||||
manifestData,
|
||||
incomingRequest,
|
||||
incomingResponse,
|
||||
pathname,
|
||||
middleware: isDefaultPrerendered404(fourOhFourRoute.route) ? undefined : middleware,
|
||||
request,
|
||||
routeData: fourOhFourRoute.route,
|
||||
});
|
||||
response = await renderContext.render(fourOhFourRoute.preloadedComponent);
|
||||
}
|
||||
}
|
||||
|
||||
// We remove the internally-used header before we send the response to the user agent.
|
||||
|
|
|
@ -7,6 +7,7 @@ const currentLocale = Astro.currentLocale;
|
|||
</head>
|
||||
<body>
|
||||
<h1>404 - Not Found</h1>
|
||||
<h2>Custom 404</h2>
|
||||
<p>Current Locale: {currentLocale ? currentLocale : "none"}</p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -83,6 +83,12 @@ describe('[DEV] i18n routing', () => {
|
|||
assert.equal((await response.text()).includes('Endurance'), true);
|
||||
});
|
||||
|
||||
it('should render the 404.astro file', async () => {
|
||||
const response = await fixture.fetch('/do-not-exist');
|
||||
assert.equal(response.status, 404);
|
||||
assert.match(await response.text(), /Custom 404/);
|
||||
});
|
||||
|
||||
it('should return the correct locale on 404 page for non existing default locale page', async () => {
|
||||
const response = await fixture.fetch('/es/nonexistent-page');
|
||||
assert.equal(response.status, 404);
|
||||
|
|
Loading…
Add table
Reference in a new issue