/// interface Env { WORKER_NAME: string; TUNNEL_HOST: string; } declare const ALCHEMY_VERSION: string; // injected during build export default { async fetch(request: Request, env: Env) { const originalUrl = request.url; const url = new URL(request.url); url.host = env.TUNNEL_HOST; const headers = new Headers(request.headers); headers.set("alchemy-worker-name", env.WORKER_NAME); headers.set("alchemy-original-url", originalUrl); const response = await fetch(url, { method: request.method, headers, body: request.body, redirect: "manual", }); if (response.status === 530) { const error = await extractResponseError(response); const headers = new Headers(response.headers); headers.set("Content-Type", "text/html"); return new Response( renderErrorHtml({ name: env.WORKER_NAME, error, rayId: response.headers.get("cf-ray") ?? "Unknown", }), { status: 530, headers, }, ); } return response; }, } as ExportedHandler; const extractResponseError = async (response: Response) => { const error = response.headers.get("Alchemy-Error"); if (error) { return error; } let code: string | undefined; let message: string | undefined; const { promise, resolve } = Promise.withResolvers(); const rewriter = new HTMLRewriter(); rewriter.on("h1", { text(text) { if (code) return; const match = text.text.match(/(\d+)/); if (match) { code = match[1]; } }, }); rewriter.on("h2", { text(text) { if (message) return; message = text.text; }, }); rewriter.onDocument({ end() { resolve([code, message].filter(Boolean).join(": ") || "Unknown"); }, }); await rewriter.transform(response).text(); // consume response body so rewriter runs return promise; }; const renderErrorHtml = (props: { name: string; error: string; rayId: string; }) => ` Alchemy | Tunnel Error 530: Tunnel Error The worker "${props.name}" could not be reached. Please ensure that alchemy dev is running and tunnel mode is enabled for the worker. Error: ${props.error} Ray ID: ${props.rayId} Learn more about tunnel mode in Alchemy. Alchemy ${ALCHEMY_VERSION} `;
The worker "${props.name}" could not be reached.
Please ensure that alchemy dev is running and tunnel mode is enabled for the worker.
alchemy dev
Learn more about tunnel mode in Alchemy.
Alchemy ${ALCHEMY_VERSION}