UNPKG

ethercalc

Version:

Multi-User Spreadsheet Server — TypeScript rewrite (Cloudflare fullstack)

59 lines (55 loc) 2.23 kB
/** * Native WebSocket route. `GET /_ws/:room?user=<user>&auth=<hmac>` proxies * the WS handshake through to the room DO's `/_do/ws` endpoint. The DO * then accepts the socket via `state.acceptWebSocket` (hibernation API) * and handles every subsequent message frame. * * Excluded from the coverage gate for the same reason as the sibling * `routes/rooms.ts`: workerd istanbul can't trace hits through Hono's * bundled invocation path. Test coverage comes from integration (workers * pool) tests in `test/ws.test.ts`. * * Reference: AGENTS.md sec 10.1 (native WS transport) and sec 7 item 11 * (hibernation invariants). */ /* istanbul ignore file */ import type { Hono } from 'hono'; import { roomStub } from '../lib/do-dispatch.ts'; import { encodeRoom } from '../lib/room-name.ts'; import type { Env } from '../env.ts'; /** * Build the DO-internal URL that corresponds to the inbound WS request. * Preserves `user`, `auth`, and `room` query params end-to-end so the DO * handshake handler can seed its attachment payload correctly. */ function buildDoUrl(room: string, url: URL): string { const encoded = encodeRoom(room); const params = new URLSearchParams(); const user = url.searchParams.get('user'); const auth = url.searchParams.get('auth'); if (user !== null) params.set('user', user); if (auth !== null) params.set('auth', auth); params.set('room', encoded); return `https://do.local/_do/ws?${params.toString()}`; } export function registerWs(app: Hono<{ Bindings: Env }>): void { app.get('/_ws/:room', async (c) => { const upgrade = c.req.header('upgrade') ?? c.req.header('Upgrade') ?? ''; if (upgrade.toLowerCase() !== 'websocket') { return c.text('Expected Upgrade: websocket', 426); } const room = c.req.param('room') ?? ''; const stub = roomStub(c.env, room); const doUrl = buildDoUrl(room, new URL(c.req.url)); const fwd = new Headers({ Upgrade: 'websocket' }); const sandstormPerms = c.req.header('X-Sandstorm-Permissions'); if (sandstormPerms) { fwd.set('X-Sandstorm-Permissions', sandstormPerms); } const req = new Request(doUrl, { method: 'GET', headers: fwd, }); return stub.fetch(req); }); }