diff --git a/docs/1.guide/2.hooks.md b/docs/1.guide/2.hooks.md index 697ec2e..006843c 100644 --- a/docs/1.guide/2.hooks.md +++ b/docs/1.guide/2.hooks.md @@ -15,11 +15,11 @@ Crossws provides a cross-platform API to define WebSocket servers. An implementa import { defineHooks } from "crossws"; const hooks = defineHooks({ - upgrade(req) { - console.log(`[ws] upgrading ${req.url}...`) + upgrade(request) { + console.log(`[ws] upgrading ${request.url}...`); return { - headers: {} - } + headers: {}, + }; }, open(peer) { @@ -42,3 +42,75 @@ const hooks = defineHooks({ }, }); ``` + +## Context + +You can store data in the `context` property of the `request` object during the `upgrade` hook or the `peer` object during the other hooks. This data will be shared in all hooks for the lifetime of the connection. + +> [!NOTE] +> context can be volatile in some environments like `cloudflare-durable` + +```ts +import { defineHooks } from "crossws"; + +const hooks = defineHooks({ + upgrade(request) { + request.context.data = "myData"; + }, + + open(peer) { + console.log(peer.context.data); // myData + }, + + message(peer, message) { + console.log(peer.context.data); // myData + }, + + close(peer, details) { + console.log(peer.context.data); // myData + }, +}); +``` + +## Authentication + +During the `upgrade` hook it is possible to authenticate the user before upgrading the connection. If the user is not authenticated, you can throw a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) **as error** to prevent the connection from being upgraded. + +```ts +import { defineHooks } from "crossws"; + +const authToken = "Bearer myToken123"; + +const hooks = defineHooks({ + upgrade(request) { + const authHeader = request.headers.get("Authorization"); + + if (!authHeader || !authHeader.startsWith("Basic ")) { + return new Response("Unauthorized", { + status: 401, + headers: { + "WWW-Authenticate": + 'Basic realm="Websocket Authentication", charset="UTF-8"', + }, + }); + } + + const base64Credentials = authHeader.split(" ")[1]; + const [username, password] = atob(base64Credentials).split(":"); + + if (username !== "myUsername" || password !== "myPassword") { + return new Response("Unauthorized", { + status: 401, + headers: { + "WWW-Authenticate": + 'Basic realm="Websocket Authentication", charset="UTF-8"', + }, + }); + } + + return { + headers: {}, // Optionally return custom headers + }; + }, +}); +```