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 { APIContext, MiddlewareHandler, SSRManifest } from '../@types/astro.js';
|
||||||
import type { SSRManifestI18n } from '../core/app/types.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 {
|
import {
|
||||||
type MiddlewarePayload,
|
type MiddlewarePayload,
|
||||||
normalizeTheLocale,
|
normalizeTheLocale,
|
||||||
|
@ -65,6 +65,12 @@ export function createI18nMiddleware(
|
||||||
return async (context, next) => {
|
return async (context, next) => {
|
||||||
const response = await next();
|
const response = await next();
|
||||||
const type = response.headers.get(ROUTE_TYPE_HEADER);
|
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 the route we're processing is not a page, then we ignore it
|
||||||
if (type !== 'page' && type !== 'fallback') {
|
if (type !== 'page' && type !== 'fallback') {
|
||||||
return response;
|
return response;
|
||||||
|
|
|
@ -63,7 +63,6 @@ export async function handleRequest({
|
||||||
url,
|
url,
|
||||||
pathname: resolvedPathname,
|
pathname: resolvedPathname,
|
||||||
body,
|
body,
|
||||||
origin,
|
|
||||||
pipeline,
|
pipeline,
|
||||||
manifestData,
|
manifestData,
|
||||||
incomingRequest: incomingRequest,
|
incomingRequest: incomingRequest,
|
||||||
|
|
|
@ -127,7 +127,6 @@ type HandleRoute = {
|
||||||
url: URL;
|
url: URL;
|
||||||
pathname: string;
|
pathname: string;
|
||||||
body: ArrayBuffer | undefined;
|
body: ArrayBuffer | undefined;
|
||||||
origin: string;
|
|
||||||
manifestData: ManifestData;
|
manifestData: ManifestData;
|
||||||
incomingRequest: http.IncomingMessage;
|
incomingRequest: http.IncomingMessage;
|
||||||
incomingResponse: http.ServerResponse;
|
incomingResponse: http.ServerResponse;
|
||||||
|
@ -139,7 +138,6 @@ export async function handleRoute({
|
||||||
url,
|
url,
|
||||||
pathname,
|
pathname,
|
||||||
body,
|
body,
|
||||||
origin,
|
|
||||||
pipeline,
|
pipeline,
|
||||||
manifestData,
|
manifestData,
|
||||||
incomingRequest,
|
incomingRequest,
|
||||||
|
@ -156,12 +154,10 @@ export async function handleRoute({
|
||||||
let request: Request;
|
let request: Request;
|
||||||
let renderContext: RenderContext;
|
let renderContext: RenderContext;
|
||||||
let mod: ComponentInstance | undefined = undefined;
|
let mod: ComponentInstance | undefined = undefined;
|
||||||
let options: SSROptions | undefined = undefined;
|
|
||||||
let route: RouteData;
|
let route: RouteData;
|
||||||
const middleware = (await loadMiddleware(loader)).onRequest;
|
const middleware = (await loadMiddleware(loader)).onRequest;
|
||||||
const locals = Reflect.get(incomingRequest, clientLocalsSymbol);
|
const locals = Reflect.get(incomingRequest, clientLocalsSymbol);
|
||||||
|
|
||||||
const filePath: URL | undefined = matchedRoute.filePath;
|
|
||||||
const { preloadedComponent } = matchedRoute;
|
const { preloadedComponent } = matchedRoute;
|
||||||
route = matchedRoute.route;
|
route = matchedRoute.route;
|
||||||
// Allows adapters to pass in locals in dev mode.
|
// Allows adapters to pass in locals in dev mode.
|
||||||
|
@ -181,15 +177,6 @@ export async function handleRoute({
|
||||||
if (value) incomingResponse.setHeader(name, value);
|
if (value) incomingResponse.setHeader(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
options = {
|
|
||||||
pipeline,
|
|
||||||
filePath,
|
|
||||||
preload: preloadedComponent,
|
|
||||||
pathname,
|
|
||||||
request,
|
|
||||||
route,
|
|
||||||
};
|
|
||||||
|
|
||||||
mod = preloadedComponent;
|
mod = preloadedComponent;
|
||||||
|
|
||||||
renderContext = await RenderContext.create({
|
renderContext = await RenderContext.create({
|
||||||
|
@ -248,18 +235,17 @@ export async function handleRoute({
|
||||||
|
|
||||||
if (statusCode === 404 && response.headers.get(REROUTE_DIRECTIVE_HEADER) !== 'no') {
|
if (statusCode === 404 && response.headers.get(REROUTE_DIRECTIVE_HEADER) !== 'no') {
|
||||||
const fourOhFourRoute = await matchRoute('/404', manifestData, pipeline);
|
const fourOhFourRoute = await matchRoute('/404', manifestData, pipeline);
|
||||||
if (options && options.route !== fourOhFourRoute?.route)
|
if (fourOhFourRoute) {
|
||||||
return handleRoute({
|
renderContext = await RenderContext.create({
|
||||||
...options,
|
locals,
|
||||||
matchedRoute: fourOhFourRoute,
|
|
||||||
url: new URL(pathname, url),
|
|
||||||
body,
|
|
||||||
origin,
|
|
||||||
pipeline,
|
pipeline,
|
||||||
manifestData,
|
pathname,
|
||||||
incomingRequest,
|
middleware: isDefaultPrerendered404(fourOhFourRoute.route) ? undefined : middleware,
|
||||||
incomingResponse,
|
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.
|
// We remove the internally-used header before we send the response to the user agent.
|
||||||
|
|
|
@ -7,6 +7,7 @@ const currentLocale = Astro.currentLocale;
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>404 - Not Found</h1>
|
<h1>404 - Not Found</h1>
|
||||||
|
<h2>Custom 404</h2>
|
||||||
<p>Current Locale: {currentLocale ? currentLocale : "none"}</p>
|
<p>Current Locale: {currentLocale ? currentLocale : "none"}</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -83,6 +83,12 @@ describe('[DEV] i18n routing', () => {
|
||||||
assert.equal((await response.text()).includes('Endurance'), true);
|
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 () => {
|
it('should return the correct locale on 404 page for non existing default locale page', async () => {
|
||||||
const response = await fixture.fetch('/es/nonexistent-page');
|
const response = await fixture.fetch('/es/nonexistent-page');
|
||||||
assert.equal(response.status, 404);
|
assert.equal(response.status, 404);
|
||||||
|
|
Loading…
Add table
Reference in a new issue