Websocket Server with Durable Object Client Connection

Hi, I try build a websocket server with durable object hibernation api, on the server side I think its considered done, but on the client side, how we connect to the durable object using service binding ? I'm using cloudflare pages and want to connect to the websocket server using service binding anyone have code snippet to get address already connected on the wrangler side, but I'm strugle to get the websocket service endpoint dynamically from service binding any advise ?
7 Replies
Kholis
KholisOP5mo ago
have handler to return
case '/init': {
return new Response(
JSON.stringify({
hostname: url.hostname,
port: url.port || (url.protocol === 'https:' ? '443' : '80'),
secure: url.protocol === 'https:'
}),
{
headers: {
'Content-Type': 'application/json'
}
}
);
}
case '/init': {
return new Response(
JSON.stringify({
hostname: url.hostname,
port: url.port || (url.protocol === 'https:' ? '443' : '80'),
secure: url.protocol === 'https:'
}),
{
headers: {
'Content-Type': 'application/json'
}
}
);
}
can be curl-ed
❯ curl http://labs-dev.kholisrag.com:8000/init
{"hostname":"labs-dev.kholisrag.com","port":"80","secure":false}%
❯ curl http://labs-dev.kholisrag.com:8000/init
{"hostname":"labs-dev.kholisrag.com","port":"80","secure":false}%
but on pages side
const doNamespace = platform.env.DOWebsocket;
const id = doNamespace.idFromName('crossws');
const websocketDO = doNamespace.get(id);

// Fetch configuration from Durable Object
const response = await websocketDO.fetch('http://dummy-host/init');

if (!response.ok) {
console.warn('Failed to fetch WebSocket config, using development config');
throw new Error('Failed to fetch WebSocket config');
}

const config = await response.json<{
hostname: string;
port: string;
secure: boolean;
}>();
const doNamespace = platform.env.DOWebsocket;
const id = doNamespace.idFromName('crossws');
const websocketDO = doNamespace.get(id);

// Fetch configuration from Durable Object
const response = await websocketDO.fetch('http://dummy-host/init');

if (!response.ok) {
console.warn('Failed to fetch WebSocket config, using development config');
throw new Error('Failed to fetch WebSocket config');
}

const config = await response.json<{
hostname: string;
port: string;
secure: boolean;
}>();
seem not working.
No description
boop
boop5mo ago
Cloudflare Docs
Using WebSockets · Cloudflare Durable Objects docs
WebSockets are long-lived TCP connections that enable bi-directional, real-time communication between client and server. Both Cloudflare Durable Objects and Workers can act as WebSocket endpoints – either as a client or as a server. Because WebSocket sessions are long-lived, applications commonly use Durable Objects to accept either the client o...
boop
boop5mo ago
Basic code example: - Worker handling the request (Edit: this will be your pages function):
// Create the DO stub
const stub = Websocket_DO.get(Websocket_DO.idFromName(DO_Name));

// Pass the request to the DOs fetch handler
return await stub.fetch(Request);
// Create the DO stub
const stub = Websocket_DO.get(Websocket_DO.idFromName(DO_Name));

// Pass the request to the DOs fetch handler
return await stub.fetch(Request);
- Websocket DO:
// Create a websocket pair
const websocketPair = new WebSocketPair();
const [client, server] = Object.values(websocketPair);

// Tells the DO to accept the websocket, but to hibernate
this.ctx.acceptWebSocket(server);

// Send the upgrade response to the client to switch protocols
return new Response(null, {
status: 101,
webSocket: client,
});
// Create a websocket pair
const websocketPair = new WebSocketPair();
const [client, server] = Object.values(websocketPair);

// Tells the DO to accept the websocket, but to hibernate
this.ctx.acceptWebSocket(server);

// Send the upgrade response to the client to switch protocols
return new Response(null, {
status: 101,
webSocket: client,
});
No faffing around with hostnames
Kholis
KholisOP5mo ago
Worker handling the request (Edit: this will be your pages function):
actually I need it on the pages itself / client side. not the page function
Websocket DO:
yeah already do like this. The things is we have a CF Worker - Websocket DO I need my CF Pages / any other client / agent there to connect to websocket server. on the Pages side, since there is service binding, we don't need to connect outside of cloudflare network. so when end user open my pages, they can do websocket connection to the web server and reach / communicate with others.
boop
boop5mo ago
It is client-side, you're telling the client to switch to the websocket protocol by sending that response from the DO. Once connected, any messages that the client sends over the websocket connection will call the DO's onMessage handler You need the initial request to go through the worker/pages function in order to initialise the connection. Your /init endpoint could be used for this so that connecting clients can connect to api.yourdomain.tld/init for example
Kholis
KholisOP5mo ago
basically our CF Pages will act as a Proxy to our DOWebsocket ya? got this error before
Error fetching WebSocket config: Error: Cannot access `DOWebsocket#webSocketAddress` as Durable Object RPC is not yet supported between multiple `wrangler dev` sessions.
Error fetching WebSocket config: Error: Cannot access `DOWebsocket#webSocketAddress` as Durable Object RPC is not yet supported between multiple `wrangler dev` sessions.
does it guaranted it will work on the prod itself?
boop
boop5mo ago
No, a pages function - which is just a worker - should not be used as the client connecting to the DO with websockets. This should be your client - the browser

Did you find this page helpful?