Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure the correct data types are sent in WebSocket messages from the client to the Worker #8083

Merged
merged 3 commits into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/silver-bats-burn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cloudflare/vite-plugin": patch
---

Ensure the correct data types are sent in WebSocket messages from the client to the Worker
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,30 @@ test("closes WebSocket connection", async () => {
});
});

test("sends and receives WebSocket messages", async () => {
test("sends and receives WebSocket string messages", async () => {
await openWebSocket();
const sendButton = page.getByRole("button", { name: "Send message" });
const sendButton = page.getByRole("button", { name: "Send string" });
const messageTextBefore = await page.textContent("p");
expect(messageTextBefore).toBe("");
await sendButton.click();
await vi.waitFor(async () => {
const messageTextAfter = await page.textContent("p");
expect(messageTextAfter).toBe(
`Durable Object received client message: 'Client event'.`
`Durable Object received client message: 'Client event' of type 'string'.`
);
});
});

test("sends and receives WebSocket ArrayBuffer messages", async () => {
await openWebSocket();
const sendButton = page.getByRole("button", { name: "Send ArrayBuffer" });
const messageTextBefore = await page.textContent("p");
expect(messageTextBefore).toBe("");
await sendButton.click();
await vi.waitFor(async () => {
const messageTextAfter = await page.textContent("p");
expect(messageTextAfter).toBe(
`Durable Object received client message: '[object ArrayBuffer]' of type 'object'.`
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
<h1>WebSockets playground</h1>
<button id="open" aria-label="Open WebSocket">Open</button>
<button id="close" aria-label="Close WebSocket">Close</button>
<button id="send" aria-label="Send message">Send</button>
<button id="send-string" aria-label="Send string">Send string</button>
<button id="send-array-buffer" aria-label="Send ArrayBuffer">
Send ArrayBuffer
</button>
<h2 id="status">WebSocket closed</h2>
<p id="message"></p>
</main>
Expand All @@ -18,13 +21,17 @@ <h2 id="status">WebSocket closed</h2>
let ws;
const openButton = document.querySelector("#open");
const closeButton = document.querySelector("#close");
const sendButton = document.querySelector("#send");
const sendStringButton = document.querySelector("#send-string");
const sendArrayBufferButton = document.querySelector("#send-array-buffer");
const statusText = document.querySelector("#status");
const messageText = document.querySelector("#message");

openButton.addEventListener("click", () => open());
closeButton.addEventListener("click", () => close());
sendButton.addEventListener("click", () => send("Client event"));
sendStringButton.addEventListener("click", () => send("Client event"));
sendArrayBufferButton.addEventListener("click", () =>
send(new ArrayBuffer(10))
);

function open() {
if (ws) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ export class WebSocketServer extends DurableObject {
}

override async webSocketMessage(ws: WebSocket, data: string | ArrayBuffer) {
const decoder = new TextDecoder();
const message = typeof data === "string" ? data : decoder.decode(data);

ws.send(`Durable Object received client message: '${message}'.`);
ws.send(
`Durable Object received client message: '${data}' of type '${typeof data}'.`
);
}
}

Expand Down
10 changes: 8 additions & 2 deletions packages/vite-plugin-cloudflare/src/websockets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,14 @@ export function handleWebSocket(
});

// Forward client events to Worker
clientWebSocket.on("message", (event: ArrayBuffer | string) => {
workerWebSocket.send(event);
clientWebSocket.on("message", (data, isBinary) => {
workerWebSocket.send(
isBinary
? Array.isArray(data)
? Buffer.concat(data)
: data
: data.toString()
);
});
clientWebSocket.on("error", (error) => {
logger.error(`WebSocket error:\n${error.stack || error.message}`, {
Expand Down
Loading