aboutsummaryrefslogtreecommitdiff
path: root/docs/guides/websocket
diff options
context:
space:
mode:
Diffstat (limited to 'docs/guides/websocket')
-rw-r--r--docs/guides/websocket/compression.md31
-rw-r--r--docs/guides/websocket/context.md72
-rw-r--r--docs/guides/websocket/index.json4
-rw-r--r--docs/guides/websocket/pubsub.md38
-rw-r--r--docs/guides/websocket/simple.md33
-rw-r--r--docs/guides/websocket/upgrade.md28
6 files changed, 206 insertions, 0 deletions
diff --git a/docs/guides/websocket/compression.md b/docs/guides/websocket/compression.md
new file mode 100644
index 000000000..e98d8f0c9
--- /dev/null
+++ b/docs/guides/websocket/compression.md
@@ -0,0 +1,31 @@
+---
+name: Enable compression for WebSocket messages
+---
+
+Per-message compression can be enabled with the `perMessageDeflate` parameter. When set, all messages will be compressed using the [permessage-deflate](https://tools.ietf.org/html/rfc7692) WebSocket extension.
+
+```ts
+Bun.serve({
+ // ...
+ websocket: {
+ // enable compression
+ perMessageDeflate: true,
+ },
+});
+```
+
+---
+
+To enable compression for individual messages, pass `true` as the second parameter to `ws.send()`.
+
+```ts
+Bun.serve({
+ // ...
+ websocket: {
+ async message(ws, message) {
+ // send a compressed message
+ ws.send("Hello world!", true);
+ },
+ },
+});
+```
diff --git a/docs/guides/websocket/context.md b/docs/guides/websocket/context.md
new file mode 100644
index 000000000..9e387d685
--- /dev/null
+++ b/docs/guides/websocket/context.md
@@ -0,0 +1,72 @@
+---
+name: Set per-socket contextual data on a WebSocket
+---
+
+When building a WebSocket server, it's typically necessary to store some identifying information or context associated with each connected client.
+
+With [Bun.serve()](/docs/api/websockets#contextual-data), this "contextual data" is set when the connection is initially upgraded by passing a `data` parameter in the `server.upgrade()` call.
+
+```ts
+Bun.serve<{ socketId: number }>({
+ fetch(req, server) {
+ const success = server.upgrade(req, {
+ data: {
+ socketId: Math.random(),
+ },
+ });
+ if (success) return undefined;
+
+ // handle HTTP request normally
+ // ...
+ },
+ websocket: {
+ // define websocket handlers
+ async message(ws, message) {
+ // the contextual dta is available as the `data` property
+ // on the WebSocket instance
+ console.log(`Received ${message} from ${ws.data.socketId}}`);
+ },
+ },
+});
+```
+
+---
+
+It's common to read cookies/headers from the incoming request to identify the connecting client.
+
+```ts
+type WebSocketData = {
+ createdAt: number;
+ token: string;
+ userId: string;
+};
+
+// TypeScript: specify the type of `data`
+Bun.serve<WebSocketData>({
+ async fetch(req, server) {
+ // use a library to parse cookies
+ const cookies = parseCookies(req.headers.get("Cookie"));
+ const token = cookies["X-Token"];
+ const user = await getUserFromToken(ws.data.authToken);
+
+ const upgraded = server.upgrade(req, {
+ data: {
+ createdAt: Date.now(),
+ token: cookies["X-Token"],
+ userId: user.id,
+ },
+ });
+
+ if (upgraded) return undefined;
+ },
+ websocket: {
+ async message(ws, message) {
+ // save the message to a database
+ await saveMessageToDatabase({
+ message: String(message),
+ userId: ws.data.userId,
+ });
+ },
+ },
+});
+```
diff --git a/docs/guides/websocket/index.json b/docs/guides/websocket/index.json
new file mode 100644
index 000000000..cb4d71b1a
--- /dev/null
+++ b/docs/guides/websocket/index.json
@@ -0,0 +1,4 @@
+{
+ "name": "WebSocket",
+ "description": "A collection of guides relating to building WebSocket servers with Bun"
+}
diff --git a/docs/guides/websocket/pubsub.md b/docs/guides/websocket/pubsub.md
new file mode 100644
index 000000000..7403d4d2f
--- /dev/null
+++ b/docs/guides/websocket/pubsub.md
@@ -0,0 +1,38 @@
+---
+name: Build a publish-subscribe WebSocket server
+---
+
+Bun's server-side `WebSocket` API provides a native pub-sub API. Sockets can be subscribed to a set of named channels using `socket.subscribe(<name>)`; messages can be published to a channel using `socket.publish(<name>, <message>)`.
+
+This code snippet implements a simple single-channel chat server.
+
+```ts
+const server = Bun.serve<{ username: string }>({
+ fetch(req, server) {
+ const cookies = req.headers.get("cookie");
+ const username = getUsernameFromCookies(cookies);
+ const success = server.upgrade(req, { data: { username } });
+ if (success) return undefined;
+
+ return new Response("Hello world");
+ },
+ websocket: {
+ open(ws) {
+ const msg = `${ws.data.username} has entered the chat`;
+ ws.subscribe("the-group-chat");
+ ws.publish("the-group-chat", msg);
+ },
+ message(ws, message) {
+ // the server re-broadcasts incoming messages to everyone
+ ws.publish("the-group-chat", `${ws.data.username}: ${message}`);
+ },
+ close(ws) {
+ const msg = `${ws.data.username} has left the chat`;
+ ws.publish("the-group-chat", msg);
+ ws.unsubscribe("the-group-chat");
+ },
+ },
+});
+
+console.log(`Listening on ${server.hostname}:${server.port}`);
+```
diff --git a/docs/guides/websocket/simple.md b/docs/guides/websocket/simple.md
new file mode 100644
index 000000000..5aabf2fdf
--- /dev/null
+++ b/docs/guides/websocket/simple.md
@@ -0,0 +1,33 @@
+---
+name: Build a simple WebSocket server
+---
+
+Start a simple WebSocket server using [`Bun.serve`](/docs/api/http).
+
+Inside `fetch`, we attempt to upgrade incoming `ws:` or `wss:` requests to WebSocket connections.
+
+```ts
+const server = Bun.serve<{ authToken: string }>({
+ fetch(req, server) {
+ const success = server.upgrade(req);
+ if (success) {
+ // Bun automatically returns a 101 Switching Protocols
+ // if the upgrade succeeds
+ return undefined;
+ }
+
+ // handle HTTP request normally
+ return new Response("Hello world!");
+ },
+ websocket: {
+ // this is called when a message is received
+ async message(ws, message) {
+ console.log(`Received ${message}`);
+ // send back a message
+ ws.send(`You said: ${message}`);
+ },
+ },
+});
+
+console.log(`Listening on localhost:\${server.port}`);
+```
diff --git a/docs/guides/websocket/upgrade.md b/docs/guides/websocket/upgrade.md
new file mode 100644
index 000000000..cec8c3802
--- /dev/null
+++ b/docs/guides/websocket/upgrade.md
@@ -0,0 +1,28 @@
+---
+name: Upgrade an HTTP request to a WebSocket connection
+---
+
+Inside `fetch`, use the `server.upgrade()` function to upgrade an incoming `Request` to a WebSocket connection. Bun automatically returns a 101 Switching Protocols response if the upgrade succeeds.
+
+Refer to the [WebSocket docs](/docs/api/websockets) for more information on building WebSocket servers.
+
+```ts
+const server = Bun.serve<{ authToken: string }>({
+ fetch(req, server) {
+ const success = server.upgrade(req);
+ if (success) {
+ // Bun automatically returns a 101 Switching Protocols
+ // if the upgrade succeeds
+ return undefined;
+ }
+
+ // handle HTTP request normally
+ return new Response("Hello world!");
+ },
+ websocket: {
+ // define websocket handlers
+ },
+});
+
+console.log(`Listening on localhost:\${server.port}`);
+```