diff --git a/.changeset/famous-gorillas-confess.md b/.changeset/famous-gorillas-confess.md new file mode 100644 index 000000000000..7e12528681a0 --- /dev/null +++ b/.changeset/famous-gorillas-confess.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fixes an issue where `Astro.locals` coming from an adapter weren't available in the `404.astro`, when using the `astro dev` command, diff --git a/packages/astro/src/vite-plugin-astro-server/route.ts b/packages/astro/src/vite-plugin-astro-server/route.ts index da4f309dad37..025ba1e75cbe 100644 --- a/packages/astro/src/vite-plugin-astro-server/route.ts +++ b/packages/astro/src/vite-plugin-astro-server/route.ts @@ -246,7 +246,7 @@ export async function handleRoute({ const fourOhFourRoute = await matchRoute('/404', manifestData, pipeline); if (fourOhFourRoute) { renderContext = await RenderContext.create({ - locals: {}, + locals, pipeline, pathname, middleware: isDefaultPrerendered404(fourOhFourRoute.route) ? undefined : middleware, diff --git a/packages/astro/test/custom-404-locals.test.js b/packages/astro/test/custom-404-locals.test.js new file mode 100644 index 000000000000..246e9e31e4b0 --- /dev/null +++ b/packages/astro/test/custom-404-locals.test.js @@ -0,0 +1,59 @@ +import assert from 'node:assert/strict'; +import { after, before, describe, it } from 'node:test'; +import * as cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; + +describe('Custom 404 locals', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/custom-404-locals/', + 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); + + assert.equal($('h1').text(), 'Home'); + }); + + it('renders 404 for /a', async () => { + const res = await fixture.fetch('/a'); + assert.equal(res.status, 404); + + const html = await res.text(); + $ = cheerio.load(html); + + assert.equal($('h1').text(), 'Page not found'); + assert.equal($('p.message').text(), 'This 404 is a dynamic HTML file.'); + assert.equal($('p.runtime').text(), 'locals'); + }); + + it('renders 404 for /404-return', async () => { + const res = await fixture.fetch('/404-return'); + assert.equal(res.status, 404); + + const html = await res.text(); + $ = cheerio.load(html); + + assert.equal($('h1').text(), 'Page not found'); + assert.equal($('p.message').text(), 'This 404 is a dynamic HTML file.'); + assert.equal($('p.runtime').text(), 'locals'); + }); + }); +}); diff --git a/packages/astro/test/fixtures/custom-404-locals/astro.config.mjs b/packages/astro/test/fixtures/custom-404-locals/astro.config.mjs new file mode 100644 index 000000000000..8e5335b3d5c6 --- /dev/null +++ b/packages/astro/test/fixtures/custom-404-locals/astro.config.mjs @@ -0,0 +1,19 @@ +import { defineConfig } from 'astro/config'; + +// https://astro.build/config +export default defineConfig({ + integrations: [{ + name: 'locals-integration', + hooks: { + 'astro:server:setup': ({ server }) => { + server.middlewares.use(async function middleware(req, res, next) { + const clientLocalsSymbol = Symbol.for('astro.locals'); + Reflect.set(req, clientLocalsSymbol, { + runtime: 'locals' + }); + next(); + }); + }, + }, + }] +}); diff --git a/packages/astro/test/fixtures/custom-404-locals/package.json b/packages/astro/test/fixtures/custom-404-locals/package.json new file mode 100644 index 000000000000..6fe4651b3a6c --- /dev/null +++ b/packages/astro/test/fixtures/custom-404-locals/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/custom-404-locals", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*" + } +} diff --git a/packages/astro/test/fixtures/custom-404-locals/src/pages/404-return.astro b/packages/astro/test/fixtures/custom-404-locals/src/pages/404-return.astro new file mode 100644 index 000000000000..85c7644717e6 --- /dev/null +++ b/packages/astro/test/fixtures/custom-404-locals/src/pages/404-return.astro @@ -0,0 +1,5 @@ +--- +return new Response(null, { status: 404 }); +--- + +I should never load \ No newline at end of file diff --git a/packages/astro/test/fixtures/custom-404-locals/src/pages/404.astro b/packages/astro/test/fixtures/custom-404-locals/src/pages/404.astro new file mode 100644 index 000000000000..867ca600c980 --- /dev/null +++ b/packages/astro/test/fixtures/custom-404-locals/src/pages/404.astro @@ -0,0 +1,13 @@ +--- +const runtime = Astro.locals.runtime +--- + + + Not Found - Custom 404 + + +

Page not found

+

This 404 is a dynamic HTML file.

+

{runtime}

+ + \ No newline at end of file diff --git a/packages/astro/test/fixtures/custom-404-locals/src/pages/index.astro b/packages/astro/test/fixtures/custom-404-locals/src/pages/index.astro new file mode 100644 index 000000000000..cf5ef9b586c6 --- /dev/null +++ b/packages/astro/test/fixtures/custom-404-locals/src/pages/index.astro @@ -0,0 +1,11 @@ +--- +--- + + + + Custom 404 + + +

Home

+ + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6279bfc08916..15f9f2303831 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2888,6 +2888,12 @@ importers: specifier: workspace:* version: link:../../.. + packages/astro/test/fixtures/custom-404-locals: + dependencies: + astro: + specifier: workspace:* + version: link:../../.. + packages/astro/test/fixtures/custom-404-loop-case-1: dependencies: astro: