fix(core): establish request context at every server-code entry point
Wraps the three additional entry points where user server code runs outside fetchHandler's own context wrap: - the server-function RPC path (/__wrnexus/rpc) intercepted before handlers.fetch in the dev server (index.ts) - what server.fn() travels - the service RPC path (isRpcPath) inside fetchHandler, which runs implement()/implementStream() service code before ctx existed - the HMR-sync handler, which runs real load blocks/actions via dispatch() Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
680ea73975
commit
c7e40154ca
3 files changed
+94
-32
No files matched your search
@@ -1048,22 +1048,28 @@ export function createHandlers(deps: RuntimeDeps): Handlers {
|
||||
withSecurityHeaders(req, res, mode, runtimeSecurity, nonce);
|
||||
|
||||
if (isRpcPath(url.pathname)) {
|
||||
let services: Map<string, ServiceImplementation | StreamImplementation>;
|
||||
try {
|
||||
services = await loadServices();
|
||||
} catch (error) {
|
||||
const app = process.env.WRNEXUS_APP_NAME ?? "app";
|
||||
const detail = error instanceof Error ? (error.stack ?? error.message) : String(error);
|
||||
console.error(`[wrnexus] RPC request failed to load services (${app})\n${detail}`);
|
||||
return secure(
|
||||
Response.json(
|
||||
{ ok: false, code: "RPC_UNKNOWN", message: "Service unavailable", retryable: false },
|
||||
{ headers: { "cache-control": "private, no-store" } },
|
||||
),
|
||||
);
|
||||
}
|
||||
const rpcResponse = await handleRpcRequest(req, url, services);
|
||||
if (rpcResponse) return secure(rpcResponse);
|
||||
// Service RPC handlers run user code (implement()/implementStream()), so
|
||||
// they need the same request context an ordinary API route gets.
|
||||
const rpcCtx = createContext(req, url);
|
||||
const rpcOutcome = await runWithRequestContext(rpcCtx, async () => {
|
||||
let services: Map<string, ServiceImplementation | StreamImplementation>;
|
||||
try {
|
||||
services = await loadServices();
|
||||
} catch (error) {
|
||||
const app = process.env.WRNEXUS_APP_NAME ?? "app";
|
||||
const detail = error instanceof Error ? (error.stack ?? error.message) : String(error);
|
||||
console.error(`[wrnexus] RPC request failed to load services (${app})\n${detail}`);
|
||||
return secure(
|
||||
Response.json(
|
||||
{ ok: false, code: "RPC_UNKNOWN", message: "Service unavailable", retryable: false },
|
||||
{ headers: { "cache-control": "private, no-store" } },
|
||||
),
|
||||
);
|
||||
}
|
||||
const rpcResponse = await handleRpcRequest(req, url, services);
|
||||
return rpcResponse ? secure(rpcResponse) : undefined;
|
||||
});
|
||||
if (rpcOutcome) return rpcOutcome;
|
||||
}
|
||||
|
||||
const preflight = createCorsPreflightResponse(req, deps.security);
|
||||
@@ -2179,21 +2185,23 @@ export function createHandlers(deps: RuntimeDeps): Handlers {
|
||||
headers.set("x-wrnexus-hmr", "1");
|
||||
const req = new Request(url, { headers });
|
||||
const ctx = createContext(req, url);
|
||||
initializeRequestCache(ctx);
|
||||
ctx.locals.cspNonce = randomNonce();
|
||||
if (deps.i18n) {
|
||||
ctx.lang = resolveLang(
|
||||
deps.i18n,
|
||||
ctx.cookies.get(deps.i18n.cookie.name),
|
||||
req.headers.get("accept-language"),
|
||||
const html = await runWithRequestContext(ctx, async () => {
|
||||
initializeRequestCache(ctx);
|
||||
ctx.locals.cspNonce = randomNonce();
|
||||
if (deps.i18n) {
|
||||
ctx.lang = resolveLang(
|
||||
deps.i18n,
|
||||
ctx.cookies.get(deps.i18n.cookie.name),
|
||||
req.headers.get("accept-language"),
|
||||
);
|
||||
ctx.t = makeT(deps.i18n, ctx.lang);
|
||||
}
|
||||
const res = withContextHeaders(
|
||||
ctx,
|
||||
await runMiddleware(await resolveMiddleware(), ctx, () => dispatch(ctx)),
|
||||
);
|
||||
ctx.t = makeT(deps.i18n, ctx.lang);
|
||||
}
|
||||
const res = withContextHeaders(
|
||||
ctx,
|
||||
await runMiddleware(await resolveMiddleware(), ctx, () => dispatch(ctx)),
|
||||
);
|
||||
const html = await res.text();
|
||||
return res.text();
|
||||
});
|
||||
ws.send(JSON.stringify({ type: "html", html }));
|
||||
} catch (err) {
|
||||
if (mode === "development") console.error(err);
|
||||
|
||||
Reference in new issue
Block a user