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

fix(routing): don't attach locals to request (#12647)

* fix(routing): don't attach locals to request

* apply feedback
This commit is contained in:
Emanuele Stoppa 2024-12-06 10:31:23 +00:00 committed by GitHub
parent a71e9b93b3
commit 8f8f15ca1d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 37 additions and 20 deletions

View file

@ -259,7 +259,6 @@ export class App {
this.#logger.error(null, error.stack!);
return this.#renderError(request, { status: 500, error, clientAddress });
}
Reflect.set(request, clientLocalsSymbol, locals);
}
if (!routeData) {
routeData = this.match(request);

View file

@ -1,4 +1,3 @@
import { setGetEnv } from '../env/runtime.js';
import { createI18nMiddleware } from '../i18n/middleware.js';
import type { ComponentInstance } from '../types/astro.js';
import type { MiddlewareHandler, RewritePayload } from '../types/public/common.js';
@ -10,8 +9,6 @@ import type {
SSRResult,
} from '../types/public/internal.js';
import { createOriginCheckMiddleware } from './app/middlewares.js';
import { AstroError } from './errors/errors.js';
import { AstroErrorData } from './errors/index.js';
import type { Logger } from './logger/core.js';
import { NOOP_MIDDLEWARE_FN } from './middleware/noop-middleware.js';
import { sequence } from './middleware/sequence.js';

View file

@ -39,6 +39,11 @@ export type CreateContext = {
* User defined default locale
*/
defaultLocale: string;
/**
* Initial value of the locals
*/
locals: App.Locals;
};
/**
@ -49,6 +54,7 @@ function createContext({
params = {},
userDefinedLocales = [],
defaultLocale = '',
locals,
}: CreateContext): APIContext {
let preferredLocale: string | undefined = undefined;
let preferredLocaleList: string[] | undefined = undefined;
@ -104,15 +110,15 @@ function createContext({
return clientIpAddress;
},
get locals() {
let locals = Reflect.get(request, clientLocalsSymbol);
// TODO: deprecate this usage. This is used only by the edge middleware for now, so its usage should be basically none.
let _locals = locals ?? Reflect.get(request, clientLocalsSymbol);
if (locals === undefined) {
locals = {};
Reflect.set(request, clientLocalsSymbol, locals);
_locals = {};
}
if (typeof locals !== 'object') {
if (typeof _locals !== 'object') {
throw new AstroError(AstroErrorData.LocalsNotAnObject);
}
return locals;
return _locals;
},
set locals(_) {
throw new AstroError(AstroErrorData.LocalsReassigned);

View file

@ -24,8 +24,6 @@ export interface CreateRequestOptions {
routePattern: string;
}
const clientLocalsSymbol = Symbol.for('astro.locals');
/**
* Used by astro internals to create a web standard request object.
*
@ -39,7 +37,6 @@ export function createRequest({
method = 'GET',
body = undefined,
logger,
locals,
isPrerendered = false,
routePattern,
}: CreateRequestOptions): Request {
@ -93,7 +90,5 @@ export function createRequest({
});
}
Reflect.set(request, clientLocalsSymbol, locals ?? {});
return request;
}

View file

@ -160,6 +160,7 @@ export async function handleRoute({
let mod: ComponentInstance | undefined = undefined;
let route: RouteData;
const middleware = (await loadMiddleware(loader)).onRequest;
// This is required for adapters to set locals in dev mode. They use a dev server middleware to inject locals to the `http.IncomingRequest` object.
const locals = Reflect.get(incomingRequest, clientLocalsSymbol);
const { preloadedComponent } = matchedRoute;
@ -242,7 +243,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,

View file

@ -16,4 +16,21 @@ describe('createAPIContext', () => {
assert.equal(context.clientAddress, '192.0.2.43');
});
it('should return the correct locals', () => {
const request = new Request('http://example.com', {
headers: {
'x-forwarded-for': '192.0.2.43, 172.16.58.3',
},
});
const context = createContext({
request,
locals: {
foo: 'bar',
},
});
assert.deepEqual(context.locals, { foo: 'bar' });
});
});

View file

@ -87,16 +87,18 @@ describe('endpoints', () => {
url: '/streaming',
});
const locals = { cancelledByTheServer: false };
req[Symbol.for('astro.locals')] = locals;
container.handle(req, res);
await new Promise((resolve) => setTimeout(resolve, 500));
res.emit('close');
await done;
try {
await done;
assert.equal(locals.cancelledByTheServer, true);
assert.ok(true);
} catch (err) {
assert.fail(err)
}
});
});