0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-16 21:46:22 -05:00

fix(middleware): instantiate locals if the adapter does not (#8800)

This commit is contained in:
Arsh 2023-10-12 14:36:34 +00:00 committed by GitHub
parent 3bef32f81c
commit 391729686b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 67 additions and 18 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Fixed an issue where attempting to assign a variable onto locals threw an error.

View file

@ -57,7 +57,9 @@ export function createAPIContext({
ResponseWithEncoding,
url: new URL(request.url),
get clientAddress() {
if (!(clientAddressSymbol in request)) {
if (clientAddressSymbol in request) {
return Reflect.get(request, clientAddressSymbol) as string;
}
if (adapterName) {
throw new AstroError({
...AstroErrorData.ClientAddressNotAvailable,
@ -66,26 +68,31 @@ export function createAPIContext({
} else {
throw new AstroError(AstroErrorData.StaticClientAddressNotAvailable);
}
},
get locals() {
let locals = Reflect.get(request, clientLocalsSymbol)
if (locals === undefined) {
locals = {}
Reflect.set(request, clientLocalsSymbol, locals)
}
return Reflect.get(request, clientAddressSymbol);
if (typeof locals !== 'object') {
throw new AstroError(AstroErrorData.LocalsNotAnObject);
}
return locals;
},
} as APIContext;
// We define a custom property, so we can check the value passed to locals
Object.defineProperty(context, 'locals', {
enumerable: true,
get() {
return Reflect.get(request, clientLocalsSymbol);
},
set(val) {
// We define a custom property, so we can check the value passed to locals
set locals(val) {
if (typeof val !== 'object') {
throw new AstroError(AstroErrorData.LocalsNotAnObject);
} else {
Reflect.set(request, clientLocalsSymbol, val);
}
},
});
} satisfies APIContext;
return context;
}

View file

@ -0,0 +1,6 @@
import { defineMiddleware } from 'astro:middleware';
export const onRequest = defineMiddleware(({ url, locals }, next) => {
if (url.pathname === "/from-astro-middleware") locals.foo = "baz";
return next();
})

View file

@ -1,6 +1,6 @@
export async function post({ locals }) {
let out = { ...locals };
export async function POST({ locals }) {
const out = { ...locals };
return new Response(JSON.stringify(out), {
headers: {

View file

@ -0,0 +1,4 @@
---
const { foo } = Astro.locals;
---
<h1>{foo}</h1>

View file

@ -15,11 +15,10 @@ describe('API routes', () => {
await fixture.build();
});
it('Can render locals in page', async () => {
it('Can use locals added by node middleware', async () => {
const { handler } = await import('./fixtures/locals/dist/server/entry.mjs');
let { req, res, text } = createRequestAndResponse({
method: 'POST',
url: '/foo',
url: '/from-node-middleware',
});
let locals = { foo: 'bar' };
@ -32,6 +31,34 @@ describe('API routes', () => {
expect(html).to.contain('<h1>bar</h1>');
});
it('Throws an error when provided non-objects as locals', async () => {
const { handler } = await import('./fixtures/locals/dist/server/entry.mjs');
let { req, res, done } = createRequestAndResponse({
url: '/from-node-middleware',
});
handler(req, res, undefined, "locals");
req.send();
await done;
expect(res).to.deep.include({ statusCode: 500 });
});
it('Can use locals added by astro middleware', async () => {
const { handler } = await import('./fixtures/locals/dist/server/entry.mjs');
const { req, res, text } = createRequestAndResponse({
url: '/from-astro-middleware',
});
handler(req, res, () => {});
req.send();
const html = await text();
expect(html).to.contain('<h1>baz</h1>');
});
it('Can access locals in API', async () => {
const { handler } = await import('./fixtures/locals/dist/server/entry.mjs');
let { req, res, done } = createRequestAndResponse({