mirror of
https://github.com/withastro/astro.git
synced 2025-01-06 22:10:10 -05:00
fix(middleware): instantiate locals if the adapter does not (#8800)
This commit is contained in:
parent
3bef32f81c
commit
391729686b
7 changed files with 67 additions and 18 deletions
5
.changeset/large-colts-jump.md
Normal file
5
.changeset/large-colts-jump.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fixed an issue where attempting to assign a variable onto locals threw an error.
|
|
@ -57,7 +57,9 @@ export function createAPIContext({
|
||||||
ResponseWithEncoding,
|
ResponseWithEncoding,
|
||||||
url: new URL(request.url),
|
url: new URL(request.url),
|
||||||
get clientAddress() {
|
get clientAddress() {
|
||||||
if (!(clientAddressSymbol in request)) {
|
if (clientAddressSymbol in request) {
|
||||||
|
return Reflect.get(request, clientAddressSymbol) as string;
|
||||||
|
}
|
||||||
if (adapterName) {
|
if (adapterName) {
|
||||||
throw new AstroError({
|
throw new AstroError({
|
||||||
...AstroErrorData.ClientAddressNotAvailable,
|
...AstroErrorData.ClientAddressNotAvailable,
|
||||||
|
@ -66,26 +68,31 @@ export function createAPIContext({
|
||||||
} else {
|
} else {
|
||||||
throw new AstroError(AstroErrorData.StaticClientAddressNotAvailable);
|
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
|
||||||
|
set locals(val) {
|
||||||
// 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) {
|
|
||||||
if (typeof val !== 'object') {
|
if (typeof val !== 'object') {
|
||||||
throw new AstroError(AstroErrorData.LocalsNotAnObject);
|
throw new AstroError(AstroErrorData.LocalsNotAnObject);
|
||||||
} else {
|
} else {
|
||||||
Reflect.set(request, clientLocalsSymbol, val);
|
Reflect.set(request, clientLocalsSymbol, val);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
} satisfies APIContext;
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
6
packages/integrations/node/test/fixtures/locals/src/middleware.ts
vendored
Normal file
6
packages/integrations/node/test/fixtures/locals/src/middleware.ts
vendored
Normal 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();
|
||||||
|
})
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
export async function post({ locals }) {
|
export async function POST({ locals }) {
|
||||||
let out = { ...locals };
|
const out = { ...locals };
|
||||||
|
|
||||||
return new Response(JSON.stringify(out), {
|
return new Response(JSON.stringify(out), {
|
||||||
headers: {
|
headers: {
|
||||||
|
|
4
packages/integrations/node/test/fixtures/locals/src/pages/from-node-middleware.astro
vendored
Normal file
4
packages/integrations/node/test/fixtures/locals/src/pages/from-node-middleware.astro
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
const { foo } = Astro.locals;
|
||||||
|
---
|
||||||
|
<h1>{foo}</h1>
|
|
@ -15,11 +15,10 @@ describe('API routes', () => {
|
||||||
await fixture.build();
|
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');
|
const { handler } = await import('./fixtures/locals/dist/server/entry.mjs');
|
||||||
let { req, res, text } = createRequestAndResponse({
|
let { req, res, text } = createRequestAndResponse({
|
||||||
method: 'POST',
|
url: '/from-node-middleware',
|
||||||
url: '/foo',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let locals = { foo: 'bar' };
|
let locals = { foo: 'bar' };
|
||||||
|
@ -32,6 +31,34 @@ describe('API routes', () => {
|
||||||
expect(html).to.contain('<h1>bar</h1>');
|
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 () => {
|
it('Can access locals in API', async () => {
|
||||||
const { handler } = await import('./fixtures/locals/dist/server/entry.mjs');
|
const { handler } = await import('./fixtures/locals/dist/server/entry.mjs');
|
||||||
let { req, res, done } = createRequestAndResponse({
|
let { req, res, done } = createRequestAndResponse({
|
||||||
|
|
Loading…
Reference in a new issue