Build a WebSocket server with WebSocket ...

Hi everyone I can't get any error messages. I am trying to get my Durable Object working with Hono. My route
route.get("/ws/:id", ...myController.getAllWS);
route.get("/ws/:id", ...myController.getAllWS);
My controller
export const getAllWS = factory.createHandlers(
durableObjectMiddleware,
upgradeWebSocket(async (c) => {
return await c.get("stub").fetch(c.req.raw);
}),
);
export const getAllWS = factory.createHandlers(
durableObjectMiddleware,
upgradeWebSocket(async (c) => {
return await c.get("stub").fetch(c.req.raw);
}),
);
My middleware:
export default async function durableObjectMiddleware(
c: Context,
next: Function,
) {
const id = c.env.WEBSOCKET_MANAGER.idFromName("global");
const stub = c.env.WEBSOCKET_MANAGER.get(id);
c.set("stub", stub);
await next();
}
export default async function durableObjectMiddleware(
c: Context,
next: Function,
) {
const id = c.env.WEBSOCKET_MANAGER.idFromName("global");
const stub = c.env.WEBSOCKET_MANAGER.get(id);
c.set("stub", stub);
await next();
}
The Durable Object is exactly the code from Cloudflare https://developers.cloudflare.com/durable-objects/examples/websocket-hibernation-server/ In my Cloudflare dashboard, I can see the DO created. I can connect to the websocket, but no message can be send/receive in the websocket. webSocketMessage is never ever triggered, but if i close webSocketClose it does get triggered. I am clueless... The expected result is to receive my message back
Cloudflare Docs
Build a WebSocket server with WebSocket Hibernation · Cloudflare Du...
This example is similar to the Build a WebSocket server example, but uses the WebSocket Hibernation API. The WebSocket Hibernation API should be …
11 Replies
Elyo
ElyoOP4mo ago
My Durable Object is uploaded but doesn't work as the documentation. I copy pasted the code... How come? Whatever I send through the websocket, it should send back a message... but no reply...
async webSocketMessage(ws, message) {
// Upon receiving a message from the client, reply with the same message,
// but will prefix the message with "[Durable Object]: " and return the
// total number of connections.
ws.send(
`[Durable Object] message: ${message}, connections: ${this.ctx.getWebSockets().length}`,
);
}
async webSocketMessage(ws, message) {
// Upon receiving a message from the client, reply with the same message,
// but will prefix the message with "[Durable Object]: " and return the
// total number of connections.
ws.send(
`[Durable Object] message: ${message}, connections: ${this.ctx.getWebSockets().length}`,
);
}
No description
Elyo
ElyoOP4mo ago
Is anyone could give me an advice? Basically, I want my users to connect to the websocket and get a list of information that is updated in realtime. Is that the right way to do? I am really stuck and I don't know where I can ask beside here and my post in https://community.cloudflare.com/t/do-hibernate-not-working-when-sending-message-through-websocket/691197
Milan
Milan4mo ago
What does the code look like to accept your websocket in your durable object? Issues might include: 1. Your worker isn't actually sending a message to the Durable Object 2. You might not be using acceptWebSocket() when you create your WebSocket in the Durable Object 3. You might be sending the websocket request to the wrong endpoint in the Durable Object, in the Cloudflare example you gave you have to go to the /websocket endpoint when creating the websocket from your client. Logging always helps here, I would do console.log() throughout your worker code and your DO code to see what code paths your requests travel through.
Elyo
ElyoOP4mo ago
Thanks for the reply @milan ! 1. I do connect, but that's pretty much what I can do... 2. I am using the example and it does contain the acceptWebSocket(server) 3. I am not using the "worker" part of the example, only the Durable object. For the Worker part, this is what I shared above, I am using Hono. the router go to my controller and should create the DO. Here is my Durable object from example
import { DurableObject } from "cloudflare:workers";

export class WebSocketManager extends DurableObject {
async fetch(request) {
const webSocketPair = new WebSocketPair();
const [client, server] = Object.values(webSocketPair);
this.ctx.acceptWebSocket(server);
return new Response(null, {
status: 101,
webSocket: client,
});
}

async webSocketMessage(ws, message) {
ws.send(
`[Durable Object] message: ${message}, connections: ${this.ctx.getWebSockets().length}`,
);
}
}
import { DurableObject } from "cloudflare:workers";

export class WebSocketManager extends DurableObject {
async fetch(request) {
const webSocketPair = new WebSocketPair();
const [client, server] = Object.values(webSocketPair);
this.ctx.acceptWebSocket(server);
return new Response(null, {
status: 101,
webSocket: client,
});
}

async webSocketMessage(ws, message) {
ws.send(
`[Durable Object] message: ${message}, connections: ${this.ctx.getWebSockets().length}`,
);
}
}
I use logs everywhere, so far it goes to the fetch in the Durable Object, but no logs get triggered in the webSocketMessage... that's my issue Thanks @Alexandеr I will have a look
Milan
Milan4mo ago
Do you receive messages on the client side though? In other words, when you send a message from the client, do you get a response from the Durable Object?
Elyo
ElyoOP4mo ago
No I don't get any response from the Durable Object, that's my big issue... I can connect to it, I can send messages... but I get no response. I don't know where the message goes tbh. No reply, no logs, nothing go into webSocketMessage ...
Milan
Milan4mo ago
Can you add the following to your DO fetch:
const upgradeHeader = request.headers.get("Upgrade")
if (upgradeHeader !== "websocket") {
return new Response("Expected websocket", { status: 400 })
}
const upgradeHeader = request.headers.get("Upgrade")
if (upgradeHeader !== "websocket") {
return new Response("Expected websocket", { status: 400 })
}
Perhaps also add a webSocketClose() and console.log() in there too?
Elyo
ElyoOP4mo ago
I have a webSocketClose()
async webSocketClose(ws, code, reason, wasClean) {
console.log("Websocket closed", code, reason, wasClean);
ws.close(code, "Durable Object is closing WebSocket");
}
async webSocketClose(ws, code, reason, wasClean) {
console.log("Websocket closed", code, reason, wasClean);
ws.close(code, "Durable Object is closing WebSocket");
}
If I cut the socket abruptly, in my localhost I am getting a response
Websocket closed 1006 WebSocket disconnected without sending Close frame. false
[ERROR] Uncaught (in response) Error: The script will never generate a response.
Websocket closed 1006 WebSocket disconnected without sending Close frame. false
[ERROR] Uncaught (in response) Error: The script will never generate a response.
Only the webSocketMessage is unresponsive. The issue is only from me? I can't believe it, I am just following the example from the docs.. I want to use the websocket to provide a listing to my users, but I should use another service or do it differently? a bit loosing faith because there are no much different things to try, the code is not long and look simple. Is there a bug on DO side?
Milan
Milan4mo ago
It's certainly possible there's a bug on the DO side, but FWIW lots of people are using the WebSocket Hibernation API, and our metrics show DOs are receiving a lot of websocket messages using this API. If there was a problem with DOs, we would have heard from other customers by now.
I am just following the example from the docs..
To be clear, the DO code is similar, but the worker code is not. I'm not familiar with Hono so I can only help so much here, it would be better to open an issue on our github repo https://github.com/cloudflare/workerd/issues. I tested console.log()ing from these websocket handlers about a month ago and found that they work fine. Can test again later today, though I'm not aware of any recent code changes that would have broken logging here.
Elyo
ElyoOP4mo ago
Thanks @milan I will submit an issue, I am really stuck on something simple, don't know what is the reason so far And I really need to use DO
Milan
Milan4mo ago
I'm looking into a potential issue now, it looks like logging behavior from these handlers may have changed recently. DO team doesn't contribute to this repository so we didn't notice til now. Will update you ASAP @Elyo! Okay, quick update here. It looks like a recent change broke logging from webSocketMessage/Close/Error, but logging from these methods was never fully/correctly implemented in the first place. We're planning to get this fixed by next week. I'll post an update here when the fix goes out and we can test again. In other words, you should still be able to send/receive messages from the DO. Logging may be broken, but websockets are not, which leads me to think this is an issue with Hono.
Want results from more Discord servers?
Add your server