Alex Patterson
CDCloudflare Developers
•Created by crossbeau on 1/28/2025 in #workers-help
Cloudflare Worker Setup for Websockets is not responding to websockets on custom domain
I have this working, you shouldn't have issues there. Do you have them proxied differntly in your routes?
3 replies
CDCloudflare Developers
•Created by Alex Patterson on 1/25/2025 in #workers-help
PartyKit vs WebSocket server with WebSocket Hibernation
Maybe another way of looking at this, in this example from the docs https://developers.cloudflare.com/durable-objects/examples/websocket-hibernation-server/
Can I move this part to the Gateway, then just call an RPC?
import { DurableObject } from "cloudflare:workers";
// Worker
export default {
async fetch(request, env, ctx) {
if (request.url.endsWith("/websocket")) {
// Expect to receive a WebSocket Upgrade request.
// If there is one, accept the request and return a WebSocket Response.
const upgradeHeader = request.headers.get('Upgrade');
if (!upgradeHeader || upgradeHeader !== 'websocket') {
return new Response('Durable Object expected Upgrade: websocket', { status: 426 });
}
// This example will refer to the same Durable Object,
// since the name "foo" is hardcoded.
let id = env.WEBSOCKET_HIBERNATION_SERVER.idFromName("foo");
let stub = env.WEBSOCKET_HIBERNATION_SERVER.get(id);
return stub.fetch(request);
}
return new Response(null, {
status: 400,
statusText: 'Bad Request',
headers: {
'Content-Type': 'text/plain',
},
});
}
};
// Durable Object
export class WebSocketHibernationServer extends DurableObject {
async fetch(request) {
// Creates two ends of a WebSocket connection.
const webSocketPair = new WebSocketPair();
const [client, server] = Object.values(webSocketPair);
// Calling `acceptWebSocket()` informs the runtime that this WebSocket is to begin terminating
// request within the Durable Object. It has the effect of "accepting" the connection,
// and allowing the WebSocket to send and receive messages.
// Unlike `ws.accept()`, `state.acceptWebSocket(ws)` informs the Workers Runtime that the WebSocket
// is "hibernatable", so the runtime does not need to pin this Durable Object to memory while
// the connection is open. During periods of inactivity, the Durable Object can be evicted
// from memory, but the WebSocket connection will remain open. If at some later point the
// WebSocket receives a message, the runtime will recreate the Durable Object
// (run the `constructor`) and deliver the message to the appropriate handler.
this.ctx.acceptWebSocket(server);
return new Response(null, {
status: 101,
webSocket: client,
});
}
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 webSocketClose(ws, code, reason, wasClean) {
// If the client closes the connection, the runtime will invoke the webSocketClose() handler.
ws.close(code, "Durable Object is closing WebSocket");
}
}
import { DurableObject } from "cloudflare:workers";
// Worker
export default {
async fetch(request, env, ctx) {
if (request.url.endsWith("/websocket")) {
// Expect to receive a WebSocket Upgrade request.
// If there is one, accept the request and return a WebSocket Response.
const upgradeHeader = request.headers.get('Upgrade');
if (!upgradeHeader || upgradeHeader !== 'websocket') {
return new Response('Durable Object expected Upgrade: websocket', { status: 426 });
}
// This example will refer to the same Durable Object,
// since the name "foo" is hardcoded.
let id = env.WEBSOCKET_HIBERNATION_SERVER.idFromName("foo");
let stub = env.WEBSOCKET_HIBERNATION_SERVER.get(id);
return stub.fetch(request);
}
return new Response(null, {
status: 400,
statusText: 'Bad Request',
headers: {
'Content-Type': 'text/plain',
},
});
}
};
// Durable Object
export class WebSocketHibernationServer extends DurableObject {
async fetch(request) {
// Creates two ends of a WebSocket connection.
const webSocketPair = new WebSocketPair();
const [client, server] = Object.values(webSocketPair);
// Calling `acceptWebSocket()` informs the runtime that this WebSocket is to begin terminating
// request within the Durable Object. It has the effect of "accepting" the connection,
// and allowing the WebSocket to send and receive messages.
// Unlike `ws.accept()`, `state.acceptWebSocket(ws)` informs the Workers Runtime that the WebSocket
// is "hibernatable", so the runtime does not need to pin this Durable Object to memory while
// the connection is open. During periods of inactivity, the Durable Object can be evicted
// from memory, but the WebSocket connection will remain open. If at some later point the
// WebSocket receives a message, the runtime will recreate the Durable Object
// (run the `constructor`) and deliver the message to the appropriate handler.
this.ctx.acceptWebSocket(server);
return new Response(null, {
status: 101,
webSocket: client,
});
}
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 webSocketClose(ws, code, reason, wasClean) {
// If the client closes the connection, the runtime will invoke the webSocketClose() handler.
ws.close(code, "Durable Object is closing WebSocket");
}
}
// Worker
export default {
async fetch(request, env, ctx) {
if (request.url.endsWith("/websocket")) {
// Expect to receive a WebSocket Upgrade request.
// If there is one, accept the request and return a WebSocket Response.
const upgradeHeader = request.headers.get('Upgrade');
if (!upgradeHeader || upgradeHeader !== 'websocket') {
return new Response('Durable Object expected Upgrade: websocket', { status: 426 });
}
// This example will refer to the same Durable Object,
// since the name "foo" is hardcoded.
let id = env.WEBSOCKET_HIBERNATION_SERVER.idFromName("foo");
let stub = env.WEBSOCKET_HIBERNATION_SERVER.get(id);
return stub.fetch(request);
}
return new Response(null, {
status: 400,
statusText: 'Bad Request',
headers: {
'Content-Type': 'text/plain',
},
});
}
};
// Worker
export default {
async fetch(request, env, ctx) {
if (request.url.endsWith("/websocket")) {
// Expect to receive a WebSocket Upgrade request.
// If there is one, accept the request and return a WebSocket Response.
const upgradeHeader = request.headers.get('Upgrade');
if (!upgradeHeader || upgradeHeader !== 'websocket') {
return new Response('Durable Object expected Upgrade: websocket', { status: 426 });
}
// This example will refer to the same Durable Object,
// since the name "foo" is hardcoded.
let id = env.WEBSOCKET_HIBERNATION_SERVER.idFromName("foo");
let stub = env.WEBSOCKET_HIBERNATION_SERVER.get(id);
return stub.fetch(request);
}
return new Response(null, {
status: 400,
statusText: 'Bad Request',
headers: {
'Content-Type': 'text/plain',
},
});
}
};
2 replies