Skip to main content

websock_wasm/
builder.rs

1//! Builders for browser WebSocket clients.
2
3use websock_proto::{ConnectOptions, Error, Result, WebSocketLimits};
4
5use crate::Connection;
6use crate::connection::connect;
7
8/// Builder for creating a WebSocket client.
9///
10/// The resulting client can be reused for multiple `connect()` calls.
11#[derive(Debug, Clone)]
12pub struct ClientBuilder {
13    opts: ConnectOptions,
14}
15
16impl Default for ClientBuilder {
17    fn default() -> Self {
18        Self::new()
19    }
20}
21
22impl ClientBuilder {
23    /// Create a new client builder with default options.
24    pub fn new() -> Self {
25        Self {
26            opts: ConnectOptions::default(),
27        }
28    }
29
30    /// Replace the builder options wholesale.
31    pub fn with_options(mut self, opts: ConnectOptions) -> Self {
32        self.opts = opts;
33        self
34    }
35
36    /// Return a reference to the current options.
37    pub fn options(&self) -> &ConnectOptions {
38        &self.opts
39    }
40
41    /// Add a single header to the connection request.
42    pub fn with_header(mut self, name: impl Into<String>, value: impl Into<String>) -> Self {
43        self.opts.headers.push((name.into(), value.into()));
44        self
45    }
46
47    /// Add multiple headers to the connection request.
48    pub fn with_headers<I, K, V>(mut self, headers: I) -> Self
49    where
50        I: IntoIterator<Item = (K, V)>,
51        K: Into<String>,
52        V: Into<String>,
53    {
54        for (k, v) in headers {
55            self.opts.headers.push((k.into(), v.into()));
56        }
57        self
58    }
59
60    /// Configure WebSocket message resource limits.
61    pub fn with_limits(mut self, limits: WebSocketLimits) -> Self {
62        self.opts.limits = limits;
63        self
64    }
65
66    /// Add a single subprotocol.
67    pub fn with_protocol(mut self, protocol: impl Into<String>) -> Self {
68        self.opts.protocols.push(protocol.into());
69        self
70    }
71
72    /// Add multiple subprotocols.
73    pub fn with_protocols<I, P>(mut self, protocols: I) -> Self
74    where
75        I: IntoIterator<Item = P>,
76        P: Into<String>,
77    {
78        for p in protocols {
79            self.opts.protocols.push(p.into());
80        }
81        self
82    }
83
84    /// Build a reusable client.
85    pub fn build(self) -> Client {
86        Client { opts: self.opts }
87    }
88
89    /// Build a client using system roots (no-op in the browser).
90    pub fn with_system_roots(self) -> Result<Client> {
91        Ok(self.build())
92    }
93
94    /// Attempt to configure custom certificates (not supported in the browser).
95    pub fn with_server_certificates<I>(self, _chain: I) -> Result<Client>
96    where
97        I: IntoIterator<Item = Vec<u8>>,
98    {
99        Err(Error::Unsupported(
100            "custom certificates are not supported in browser wasm".into(),
101        ))
102    }
103
104    /// Enter the "dangerous" builder that can disable certificate verification.
105    pub fn dangerous(self) -> DangerousClientBuilder {
106        DangerousClientBuilder { opts: self.opts }
107    }
108}
109
110/// Reusable WebSocket client created by [`ClientBuilder`].
111#[derive(Debug, Clone)]
112pub struct Client {
113    opts: ConnectOptions,
114}
115
116impl Client {
117    /// Return a reference to the configured connection options.
118    pub fn options(&self) -> &ConnectOptions {
119        &self.opts
120    }
121
122    /// Establish a browser WebSocket connection.
123    pub async fn connect(&self, url: &str) -> Result<Connection> {
124        connect(url, self.opts.clone()).await
125    }
126}
127
128/// Builder that can attempt to disable certificate verification.
129pub struct DangerousClientBuilder {
130    #[allow(dead_code)]
131    opts: ConnectOptions,
132}
133
134impl DangerousClientBuilder {
135    /// Return an unsupported error, since browsers cannot disable verification.
136    pub fn with_no_certificate_verification(self) -> Result<Client> {
137        Err(Error::Unsupported(
138            "certificate verification cannot be disabled in browser wasm".into(),
139        ))
140    }
141}