Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

29 linesCodeBlameRaw
1import { renderToReadableStream } from "react-dom/server";
2import { type EntryContext, ServerRouter } from "react-router";
3
4import { makeNonce, pagePolicy } from "./lib/guard";
5
6/**
7 * Renders the whole page before sending it, then the browser hydrates it.
8 * The page runs only sudo's own scripts: React Router writes its inline
9 * scripts and preloads with this page's nonce (ServerRouter hands it to
10 * <Links>, <Scripts> and <ScrollRestoration>), and the page's policy
11 * names that nonce and nothing else (lib/guard.ts). workers/app.ts keeps
12 * the policy set here.
13 */
14export default async function handleRequest(request: Request, responseStatusCode: number, responseHeaders: Headers, routerContext: EntryContext) {
15 let status = responseStatusCode;
16 const nonce = makeNonce();
17 const body = await renderToReadableStream(<ServerRouter context={routerContext} url={request.url} nonce={nonce} />, {
18 nonce,
19 signal: request.signal,
20 onError(error: unknown) {
21 status = 500;
22 console.error(error);
23 },
24 });
25 await body.allReady;
26 responseHeaders.set("content-type", "text/html; charset=utf-8");
27 responseHeaders.set("content-security-policy", pagePolicy(nonce));
28 return new Response(body, { headers: responseHeaders, status });
29}