Because JS WebSocket cannot pass custom headers, it’s not possible to use the fly-force-instance-id header for WebSockets.
I’d argue being able to force a WebSocket connection to a specific machine is actually one of the most useful reasons to want a specific machine (so you can treat that machine’s memory as low latency shared state for clients). I’m aware there is a workaround for now, which is to use fly-replay from the server once a WebSocket request is made to an incorrect machine.
Is it possible to support fly-force-instance-id as a querystring parameter or some other mechanism that makes it useful for WebSockets?
So you actually do the replay header response before upgrading.
Bun.serve takes a fetch and a websocket key in its parameter options.
The upgrade is done inside the fetch handler, which can still return a Response.
Here’s a minimal example:
// fake fetch handler, assumes every request is a websocket upgrade request
function handleFetch(req: Request, server: Server) {
if (youWantToRedirect) {
// will replay the upgrade request to another machine
return new Response(undefined, { headers: { 'fly-replay': `instance=replace-me` } });
} else {
// keep the websocket on this machine
server.upgrade(req);
// check if upgrade was successful, etc
}
}
const server = Bun.serve({
port: 8080,
fetch: handleFetch,
websocket: /* .. some other websocket handler after upgrade */
});
I should note: this websocket replay is working well in my testing and staging but I’m not using it in production yet. It’s possible I’m missing a problem.