fix(rpc): render canonical csrf token for clients
Quality / quality (ubuntu-latest) (push) Failing after 9m46s
Quality / quality (windows-latest) (push) Canceled after 0s

This commit is contained in:
2026-08-12 18:20:14 +05:30
parent 0f201c9767
commit f73fbb7aba
4 changed files with 36 additions and 1 deletions
+6 -1
View File
@@ -4138,8 +4138,13 @@ export const REACTIVE_RUNTIME = String.raw`
}
function callServerFunction(component, functionName, args) {
var csrfMeta = document.querySelector('meta[name="wrnexus-csrf"]');
var csrfMatch = /(?:^|;\s*)wire-csrf=([^;]+)/.exec(document.cookie || "");
var csrf = csrfMatch ? decodeURIComponent(csrfMatch[1]) : "";
var csrf = csrfMeta
? csrfMeta.getAttribute("content") || ""
: csrfMatch
? decodeURIComponent(csrfMatch[1])
: "";
return fetch("/__wrnexus/rpc", {
method: "POST",
credentials: "same-origin",
+28
View File
@@ -828,6 +828,34 @@ test("component server calls send the CSRF cookie in the RPC header", async () =
expect(new Headers(request?.headers).get("x-csrf-token")).toBe("rpc token");
});
test("component server calls prefer the rendered CSRF token over stale cookies", async () => {
const win = mount(
`<meta name="wrnexus-csrf" content="current-token">` +
`<div data-scope="" data-wrn-component="Home">` +
`<button data-on-click="server.handleClick()">go</button>` +
`</div>`,
);
Object.defineProperty(win.document, "cookie", {
configurable: true,
value: "wire-csrf=stale-token",
});
let request: RequestInit | undefined;
const globals = globalThis as Record<string, unknown>;
const originalFetch = globals.fetch;
globals.fetch = async (_input: RequestInfo | URL, init?: RequestInit) => {
request = init;
return Response.json({ ok: true });
};
try {
(win.document.querySelector("button") as unknown as HTMLElement).click();
await new Promise((resolve) => setTimeout(resolve, 0));
} finally {
globals.fetch = originalFetch;
}
expect(new Headers(request?.headers).get("x-csrf-token")).toBe("current-token");
});
test("development runtime warns when a component binding names a missing function", () => {
const win = new Window() as unknown as Window & Record<string, unknown>;
win.document.body.innerHTML =