diff --git a/.changeset/pink-deers-grab.md b/.changeset/pink-deers-grab.md new file mode 100644 index 000000000000..917105007a20 --- /dev/null +++ b/.changeset/pink-deers-grab.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fix loading of `/404.astro` page when dynamic route returns 404 diff --git a/packages/astro/src/vite-plugin-astro-server/route.ts b/packages/astro/src/vite-plugin-astro-server/route.ts index 4c9b8782b266..8b8bf34828de 100644 --- a/packages/astro/src/vite-plugin-astro-server/route.ts +++ b/packages/astro/src/vite-plugin-astro-server/route.ts @@ -230,6 +230,21 @@ export async function handleRoute({ } } else { const result = await renderPage(options); + if (result.status === 404) { + const fourOhFourRoute = await matchRoute('/404', env, manifestData); + return handleRoute({ + ...options, + matchedRoute: fourOhFourRoute, + url: new URL(pathname, url), + body, + origin, + env, + manifestData, + incomingRequest, + incomingResponse, + manifest, + }); + } throwIfRedirectNotAllowed(result, config); return await writeSSRResult(request, result, incomingResponse); } diff --git a/packages/astro/test/custom-404-server.test.js b/packages/astro/test/custom-404-server.test.js new file mode 100644 index 000000000000..db09bfbab692 --- /dev/null +++ b/packages/astro/test/custom-404-server.test.js @@ -0,0 +1,42 @@ +import { expect } from 'chai'; +import * as cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; + +describe('Custom 404 server', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/custom-404-server/', + site: 'http://example.com', + }); + }); + + describe('dev', () => { + let devServer; + let $; + + before(async () => { + devServer = await fixture.startDevServer(); + }); + + after(async () => { + await devServer.stop(); + }); + + it('renders /', async () => { + const html = await fixture.fetch('/').then((res) => res.text()); + $ = cheerio.load(html); + + expect($('h1').text()).to.equal('Home'); + }); + + it('renders 404 for /a', async () => { + const html = await fixture.fetch('/a').then((res) => res.text()); + $ = cheerio.load(html); + + expect($('h1').text()).to.equal('Page not found'); + expect($('p').text()).to.equal('/a'); + }); + }); +}); diff --git a/packages/astro/test/fixtures/custom-404-server/astro.config.mjs b/packages/astro/test/fixtures/custom-404-server/astro.config.mjs new file mode 100644 index 000000000000..980ae408c9ab --- /dev/null +++ b/packages/astro/test/fixtures/custom-404-server/astro.config.mjs @@ -0,0 +1,8 @@ +import { defineConfig } from 'astro/config'; +import testAdapter from '../../test-adapter.js'; + +// https://astro.build/config +export default defineConfig({ + output: 'server', + adapter: testAdapter(), +}); diff --git a/packages/astro/test/fixtures/custom-404-server/package.json b/packages/astro/test/fixtures/custom-404-server/package.json new file mode 100644 index 000000000000..184b79c954b8 --- /dev/null +++ b/packages/astro/test/fixtures/custom-404-server/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/custom-404-server", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*" + } +} diff --git a/packages/astro/test/fixtures/custom-404-server/src/pages/404.astro b/packages/astro/test/fixtures/custom-404-server/src/pages/404.astro new file mode 100644 index 000000000000..63d560b0fb91 --- /dev/null +++ b/packages/astro/test/fixtures/custom-404-server/src/pages/404.astro @@ -0,0 +1,13 @@ +--- +const canonicalURL = new URL(Astro.url.pathname, Astro.site); +--- + + + + Not Found - Custom 404 + + +

Page not found

+

{canonicalURL.pathname}

+ + diff --git a/packages/astro/test/fixtures/custom-404-server/src/pages/[slug].astro b/packages/astro/test/fixtures/custom-404-server/src/pages/[slug].astro new file mode 100644 index 000000000000..406a10a65b40 --- /dev/null +++ b/packages/astro/test/fixtures/custom-404-server/src/pages/[slug].astro @@ -0,0 +1,6 @@ +--- +return new Response(null, { + status: 404, + statusText: 'Not Found' +}) +--- diff --git a/packages/astro/test/fixtures/custom-404-server/src/pages/index.astro b/packages/astro/test/fixtures/custom-404-server/src/pages/index.astro new file mode 100644 index 000000000000..cf5ef9b586c6 --- /dev/null +++ b/packages/astro/test/fixtures/custom-404-server/src/pages/index.astro @@ -0,0 +1,11 @@ +--- +--- + + + + Custom 404 + + +

Home

+ + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3c4781f325bb..dc5ddd7f1c23 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2520,6 +2520,12 @@ importers: specifier: workspace:* version: link:../../.. + packages/astro/test/fixtures/custom-404-server: + dependencies: + astro: + specifier: workspace:* + version: link:../../.. + packages/astro/test/fixtures/custom-assets-name: dependencies: '@astrojs/node':