From 16f12e426e5869721313bb771e2ec5b821c5452e Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Thu, 16 May 2024 14:43:30 +0100 Subject: [PATCH] fix(i18n): allow to create 404.html and 500.html (#11062) * fix(i18n): allow to create 404.html and 500.html * Update packages/astro/src/i18n/index.ts Co-authored-by: Florian Lefebvre * Update .changeset/lazy-rockets-raise.md * chore: use better matching * fix linting --------- Co-authored-by: Florian Lefebvre --- .changeset/lazy-rockets-raise.md | 5 +++++ packages/astro/src/i18n/index.ts | 10 +++++++++- packages/astro/src/i18n/middleware.ts | 6 ++++++ .../i18n-routing-prefix-always/src/pages/500.astro | 4 ++++ ...i18n-routing-manual-with-default-middleware.test.js | 5 +++-- packages/astro/test/i18n-routing.test.js | 10 ++++++++++ 6 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 .changeset/lazy-rockets-raise.md create mode 100644 packages/astro/test/fixtures/i18n-routing-prefix-always/src/pages/500.astro diff --git a/.changeset/lazy-rockets-raise.md b/.changeset/lazy-rockets-raise.md new file mode 100644 index 0000000000..44882eee67 --- /dev/null +++ b/.changeset/lazy-rockets-raise.md @@ -0,0 +1,5 @@ +--- +"astro": patch +--- + +Fixes a bug where `astro build` didn't create custom `404.html` and `500.html` when a certain combination of i18n options was applied diff --git a/packages/astro/src/i18n/index.ts b/packages/astro/src/i18n/index.ts index b8114019bd..519d5eda22 100644 --- a/packages/astro/src/i18n/index.ts +++ b/packages/astro/src/i18n/index.ts @@ -19,6 +19,14 @@ export function requestHasLocale(locales: Locales) { }; } +export function requestIs404Or500(request: Request, base = '') { + const url = new URL(request.url); + + return ( + url.pathname.startsWith(`${base}/404`) || + url.pathname.startsWith(`${base}/500`) + ); +} // Checks if the pathname has any locale export function pathHasLocale(path: string, locales: Locales): boolean { const segments = path.split('/'); @@ -317,7 +325,7 @@ export function notFound({ base, locales }: MiddlewarePayload) { if (!(isRoot || pathHasLocale(url.pathname, locales))) { if (response) { response.headers.set(REROUTE_DIRECTIVE_HEADER, 'no'); - return new Response(null, { + return new Response(response.body, { status: 404, headers: response.headers, }); diff --git a/packages/astro/src/i18n/middleware.ts b/packages/astro/src/i18n/middleware.ts index df5d63761c..9f9c7348e0 100644 --- a/packages/astro/src/i18n/middleware.ts +++ b/packages/astro/src/i18n/middleware.ts @@ -8,6 +8,7 @@ import { redirectToDefaultLocale, redirectToFallback, requestHasLocale, + requestIs404Or500, } from './index.js'; export function createI18nMiddleware( @@ -69,6 +70,11 @@ export function createI18nMiddleware( return response; } + // 404 and 500 are **known** routes (users can have their custom pages), so we need to let them be + if (requestIs404Or500(context.request, base)) { + return response; + } + const { currentLocale } = context; switch (i18n.strategy) { diff --git a/packages/astro/test/fixtures/i18n-routing-prefix-always/src/pages/500.astro b/packages/astro/test/fixtures/i18n-routing-prefix-always/src/pages/500.astro new file mode 100644 index 0000000000..8bd0a9e216 --- /dev/null +++ b/packages/astro/test/fixtures/i18n-routing-prefix-always/src/pages/500.astro @@ -0,0 +1,4 @@ + + Error + Unexpected error. + diff --git a/packages/astro/test/i18n-routing-manual-with-default-middleware.test.js b/packages/astro/test/i18n-routing-manual-with-default-middleware.test.js index bf0f6e8b97..1e609f7487 100644 --- a/packages/astro/test/i18n-routing-manual-with-default-middleware.test.js +++ b/packages/astro/test/i18n-routing-manual-with-default-middleware.test.js @@ -26,7 +26,7 @@ describe('Dev server manual routing', () => { const response = await fixture.fetch('/blog'); const text = await response.text(); assert.equal(response.status, 404); - assert.equal(text.includes('Blog should not render'), false); + assert.match(text, /Blog should not render/); }); it('should return a 200 because the custom middleware allows it', async () => { @@ -83,7 +83,8 @@ describe('SSR manual routing', () => { let request = new Request('http://example.com/blog'); let response = await app.render(request); assert.equal(response.status, 404); - assert.equal((await response.text()).includes('Blog should not render'), false); + const text = await response.text(); + assert.match(text, /Blog should not render/); }); it('should return a 200 because the custom middleware allows it', async () => { diff --git a/packages/astro/test/i18n-routing.test.js b/packages/astro/test/i18n-routing.test.js index 9723b69dfa..09581c8997 100644 --- a/packages/astro/test/i18n-routing.test.js +++ b/packages/astro/test/i18n-routing.test.js @@ -580,6 +580,16 @@ describe('[SSG] i18n routing', () => { assert.equal($('body').text().includes('Lo siento'), true); }); + it('should create a custom 404.html and 505.html', async () => { + let html = await fixture.readFile('/404.html'); + let $ = cheerio.load(html); + assert.equal($('body').text().includes("Can't find the page you're looking for."), true); + + html = await fixture.readFile('/500.html'); + $ = cheerio.load(html); + assert.equal($('body').text().includes('Unexpected error.'), true); + }); + it("should NOT render the default locale if there isn't a fallback and the route is missing", async () => { try { await fixture.readFile('/it/start/index.html');