diff options
Diffstat (limited to 'docs/api/websockets.md')
-rw-r--r-- | docs/api/websockets.md | 51 |
1 files changed, 35 insertions, 16 deletions
diff --git a/docs/api/websockets.md b/docs/api/websockets.md index 0c40a05c0..d1e1d3831 100644 --- a/docs/api/websockets.md +++ b/docs/api/websockets.md @@ -20,7 +20,7 @@ To connect to an external socket server, create an instance of `WebSocket` with const socket = new WebSocket("ws://localhost:3000"); ``` -Bun supports setting custom headers. This is a Bun-specific extension of the `WebSocket` standard. +Bun supports setting custom headers. This is a Bun-specific extension of the `WebSocket` standard. _This will not work in browsers._ ```ts const socket = new WebSocket("ws://localhost:3000", { @@ -150,11 +150,13 @@ type WebSocketData = { // TypeScript: specify the type of `data` Bun.serve<WebSocketData>({ fetch(req, server) { + const cookies = parseCookies(req.headers.get("Cookie")); server.upgrade(req, { // TS: this object must conform to WebSocketData data: { createdAt: Date.now(), channelId: new URL(req.url).searchParams.get("channelId"), + authToken: cookies["X-Token"], }, }); @@ -173,42 +175,59 @@ Bun.serve<WebSocketData>({ }); ``` +To connect to this server from the browser, create a new `WebSocket`. + +```ts#browser.js +const socket = new WebSocket("ws://localhost:3000/chat"); + +socket.addEventListener("message", event => { + console.log(event.data); +}) +``` + +The cookies that are currently set on the page will be sent with the WebSocket upgrade request and available on `req.headers` in the `fetch` handler. Parse these cookies to determine the identity of the connecting user and set the value of `data` accordingly. + ## Pub/Sub Bun's `ServerWebSocket` implementation implements a native publish-subscribe API for topic-based broadcasting. Individual sockets can `.subscribe()` to a topic (specified with a string identifier) and `.publish()` messages to all other subscribers to that topic. This topic-based broadcast API is similar to [MQTT](https://en.wikipedia.org/wiki/MQTT) and [Redis Pub/Sub](https://redis.io/topics/pubsub). ```ts -const pubsubserver = Bun.serve<{username: string}>({ +const server = Bun.serve<{ username: string }>({ fetch(req, server) { - if (req.url === '/chat') { - const cookies = getCookieFromRequest(req); - const success = server.upgrade(req, { - data: {username: cookies.username}, - }); - return success - ? undefined - : new Response('WebSocket upgrade error', {status: 400}); + const url = new URL(req.url); + if (url.pathname === "/chat") { + console.log(`upgrade!`); + const username = getUsernameFromReq(req); + const success = server.upgrade(req, { data: { username } }); + return success ? undefined : new Response("WebSocket upgrade error", { status: 400 }); } - return new Response('Hello world'); + return new Response("Hello world"); }, websocket: { open(ws) { - ws.subscribe('the-group-chat'); - ws.publish('the-group-chat', `${ws.data.username} has entered the chat`); + const msg = `${ws.data.username} has entered the chat`; + ws.subscribe("the-group-chat"); + ws.publish("the-group-chat", msg); }, message(ws, message) { // this is a group chat // so the server re-broadcasts incoming message to everyone - ws.publish('the-group-chat', `${ws.data.username}: ${message}`); + ws.publish("the-group-chat", `${ws.data.username}: ${message}`); }, close(ws) { - ws.unsubscribe('the-group-chat'); - ws.publish('the-group-chat', `${ws.data.username} has left the chat`); + const msg = `${ws.data.username} has left the chat`; + ws.unsubscribe("the-group-chat"); + ws.publish("the-group-chat", msg); }, + }, }); + +console.log(`Listening on ${server.hostname}:${server.port}`); ``` +Calling `.publish(data)` will send the message to all subscribers of a topic (excluding the socket that called `.publish()`). + ## Compression Per-message [compression](https://websockets.readthedocs.io/en/stable/topics/compression.html) can be enabled with the `perMessageDeflate` parameter. |