summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/thin-deers-sin.md5
-rw-r--r--packages/astro/src/core/app/index.ts10
-rw-r--r--packages/astro/test/fixtures/ssr-locals/src/pages/404.astro4
-rw-r--r--packages/astro/test/fixtures/ssr-locals/src/pages/500.astro4
-rw-r--r--packages/astro/test/fixtures/ssr-locals/src/pages/go-to-error-page.astro3
-rw-r--r--packages/astro/test/ssr-locals.test.js27
6 files changed, 48 insertions, 5 deletions
diff --git a/.changeset/thin-deers-sin.md b/.changeset/thin-deers-sin.md
new file mode 100644
index 000000000..25cb79b2b
--- /dev/null
+++ b/.changeset/thin-deers-sin.md
@@ -0,0 +1,5 @@
+---
+"astro": patch
+---
+
+Fixes an issue where error pages did not have access to the `Astro.locals` fields provided by the adapter.
diff --git a/packages/astro/src/core/app/index.ts b/packages/astro/src/core/app/index.ts
index 0e2d745ef..5c163005d 100644
--- a/packages/astro/src/core/app/index.ts
+++ b/packages/astro/src/core/app/index.ts
@@ -66,6 +66,7 @@ export interface RenderOptions {
}
export interface RenderErrorOptions {
+ locals?: App.Locals,
routeData?: RouteData;
response?: Response;
status: 404 | 500;
@@ -295,7 +296,7 @@ export class App {
routeData = this.match(request);
}
if (!routeData) {
- return this.#renderError(request, { status: 404 });
+ return this.#renderError(request, { locals, status: 404 });
}
const pathname = this.#getPathnameFromRequest(request);
const defaultStatus = this.#getDefaultStatusCode(routeData, pathname);
@@ -314,7 +315,7 @@ export class App {
response = await renderContext.render(await mod.page());
} catch (err: any) {
this.#logger.error(null, err.stack || err.message || String(err));
- return this.#renderError(request, { status: 500 });
+ return this.#renderError(request, { locals, status: 500 });
}
if (
@@ -322,6 +323,7 @@ export class App {
response.headers.get(REROUTE_DIRECTIVE_HEADER) !== 'no'
) {
return this.#renderError(request, {
+ locals,
response,
status: response.status as 404 | 500,
});
@@ -374,7 +376,7 @@ export class App {
*/
async #renderError(
request: Request,
- { status, response: originalResponse, skipMiddleware = false }: RenderErrorOptions
+ { locals, status, response: originalResponse, skipMiddleware = false }: RenderErrorOptions
): Promise<Response> {
const errorRoutePath = `/${status}${this.#manifest.trailingSlash === 'always' ? '/' : ''}`;
const errorRouteData = matchRoute(errorRoutePath, this.#manifestData);
@@ -397,6 +399,7 @@ export class App {
const mod = await this.#getModuleForRoute(errorRouteData);
try {
const renderContext = RenderContext.create({
+ locals,
pipeline: this.#pipeline,
middleware: skipMiddleware ? (_, next) => next() : undefined,
pathname: this.#getPathnameFromRequest(request),
@@ -410,6 +413,7 @@ export class App {
// Middleware may be the cause of the error, so we try rendering 404/500.astro without it.
if (skipMiddleware === false) {
return this.#renderError(request, {
+ locals,
status,
response: originalResponse,
skipMiddleware: true,
diff --git a/packages/astro/test/fixtures/ssr-locals/src/pages/404.astro b/packages/astro/test/fixtures/ssr-locals/src/pages/404.astro
new file mode 100644
index 000000000..66b1f7a04
--- /dev/null
+++ b/packages/astro/test/fixtures/ssr-locals/src/pages/404.astro
@@ -0,0 +1,4 @@
+---
+const { foo } = Astro.locals;
+---
+<h1 id="foo">{ foo }</h1>
diff --git a/packages/astro/test/fixtures/ssr-locals/src/pages/500.astro b/packages/astro/test/fixtures/ssr-locals/src/pages/500.astro
new file mode 100644
index 000000000..66b1f7a04
--- /dev/null
+++ b/packages/astro/test/fixtures/ssr-locals/src/pages/500.astro
@@ -0,0 +1,4 @@
+---
+const { foo } = Astro.locals;
+---
+<h1 id="foo">{ foo }</h1>
diff --git a/packages/astro/test/fixtures/ssr-locals/src/pages/go-to-error-page.astro b/packages/astro/test/fixtures/ssr-locals/src/pages/go-to-error-page.astro
new file mode 100644
index 000000000..ee962857d
--- /dev/null
+++ b/packages/astro/test/fixtures/ssr-locals/src/pages/go-to-error-page.astro
@@ -0,0 +1,3 @@
+---
+throw new Error
+--- \ No newline at end of file
diff --git a/packages/astro/test/ssr-locals.test.js b/packages/astro/test/ssr-locals.test.js
index 9fea1fed9..e4dee5025 100644
--- a/packages/astro/test/ssr-locals.test.js
+++ b/packages/astro/test/ssr-locals.test.js
@@ -7,6 +7,8 @@ import { loadFixture } from './test-utils.js';
describe('SSR Astro.locals from server', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
+ /** @type {import('./test-utils.js').App} */
+ let app;
before(async () => {
fixture = await loadFixture({
@@ -15,10 +17,10 @@ describe('SSR Astro.locals from server', () => {
adapter: testAdapter(),
});
await fixture.build();
+ app = await fixture.loadTestAdapterApp();
});
it('Can access Astro.locals in page', async () => {
- const app = await fixture.loadTestAdapterApp();
const request = new Request('http://example.com/foo');
const locals = { foo: 'bar' };
const response = await app.render(request, { locals });
@@ -29,7 +31,6 @@ describe('SSR Astro.locals from server', () => {
});
it('Can access Astro.locals in api context', async () => {
- const app = await fixture.loadTestAdapterApp();
const request = new Request('http://example.com/api');
const locals = { foo: 'bar' };
const response = await app.render(request, undefined, locals);
@@ -38,4 +39,26 @@ describe('SSR Astro.locals from server', () => {
assert.equal(body.foo, 'bar');
});
+
+ it('404.astro can access locals provided to app.render()', async () => {
+ const request = new Request('http://example.com/slkfnasf');
+ const locals = { foo: 'par' };
+ const response = await app.render(request, { locals });
+ assert.equal(response.status, 404);
+
+ const html = await response.text();
+ const $ = cheerio.load(html);
+ assert.equal($('#foo').text(), 'par');
+ });
+
+ it('500.astro can access locals provided to app.render()', async () => {
+ const request = new Request('http://example.com/go-to-error-page');
+ const locals = { foo: 'par' };
+ const response = await app.render(request, { locals });
+ assert.equal(response.status, 500);
+
+ const html = await response.text();
+ const $ = cheerio.load(html);
+ assert.equal($('#foo').text(), 'par');
+ });
});