Skip to main content

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}