dioxus_cloudflare/websocket.rs
1//! WebSocket helpers for Cloudflare Workers Durable Objects.
2//!
3//! Cloudflare Workers support WebSockets via Durable Objects: the worker
4//! upgrades the request, forwards it to a DO, which creates a [`WebSocketPair`],
5//! accepts the server socket via [`State::accept_web_socket()`], and returns
6//! the client socket as a 101 Upgrade response.
7//!
8//! # Example
9//!
10//! ```rust,ignore
11//! use worker::*;
12//! use dioxus_cloudflare::prelude::*;
13//!
14//! #[durable_object]
15//! pub struct ChatRoom {
16//! state: State,
17//! env: Env,
18//! }
19//!
20//! impl DurableObject for ChatRoom {
21//! fn new(state: State, env: Env) -> Self { Self { state, env } }
22//!
23//! async fn fetch(&self, _req: Request) -> Result<Response> {
24//! let (server, resp) = cf::websocket_upgrade()?;
25//! self.state.accept_web_socket(&server);
26//! Ok(resp)
27//! }
28//!
29//! async fn websocket_message(&self, ws: WebSocket, message: WebSocketIncomingMessage) -> Result<()> {
30//! match message {
31//! WebSocketIncomingMessage::String(text) => ws.send_with_str(&format!("echo: {text}"))?,
32//! WebSocketIncomingMessage::Binary(bytes) => ws.send_with_bytes(&bytes)?,
33//! }
34//! Ok(())
35//! }
36//! }
37//! ```
38
39use crate::error::CfError;
40
41/// Create a [`WebSocketPair`] and build the 101 Upgrade response in one call.
42///
43/// Returns `(server_socket, upgrade_response)`. The server socket should be
44/// accepted by the Durable Object's [`State::accept_web_socket()`], and the
45/// response returned from the DO's `fetch()`.
46///
47/// # Errors
48///
49/// Returns [`CfError`] if `WebSocketPair::new()` or `Response::from_websocket()`
50/// fails (e.g., called outside a Durable Object context).
51pub fn websocket_upgrade() -> Result<(worker::WebSocket, worker::Response), CfError> {
52 let pair = worker::WebSocketPair::new().map_err(CfError)?;
53 let resp = worker::Response::from_websocket(pair.client).map_err(CfError)?;
54 Ok((pair.server, resp))
55}
56
57/// Create a raw [`WebSocketPair`] without building the upgrade response.
58///
59/// Use this if you need more control over the response (e.g., custom headers).
60/// For most cases, prefer [`websocket_upgrade()`].
61///
62/// # Errors
63///
64/// Returns [`CfError`] if `WebSocketPair::new()` fails.
65pub fn websocket_pair() -> Result<worker::WebSocketPair, CfError> {
66 worker::WebSocketPair::new().map_err(CfError)
67}