reqwest_websocket/
protocol.rs

1/// A `WebSocket` message, which can be a text string or binary data.
2#[derive(Clone, Debug)]
3pub enum Message {
4    /// A text `WebSocket` message.
5    Text(String),
6
7    /// A binary `WebSocket` message.
8    Binary(Vec<u8>),
9
10    /// A ping message with the specified payload.
11    ///
12    /// The payload here must have a length less than 125 bytes.
13    ///
14    /// # WASM
15    ///
16    /// This variant is ignored for WASM targets.
17    #[cfg_attr(
18        target_arch = "wasm32",
19        deprecated(note = "This variant is ignored for WASM targets")
20    )]
21    Ping(Vec<u8>),
22
23    /// A pong message with the specified payload.
24    ///
25    /// The payload here must have a length less than 125 bytes.
26    ///
27    /// # WASM
28    ///
29    /// This variant is ignored for WASM targets.
30    #[cfg_attr(
31        target_arch = "wasm32",
32        deprecated(note = "This variant is ignored for WASM targets")
33    )]
34    Pong(Vec<u8>),
35
36    /// A close message.
37    ///
38    /// Sending this will not close the connection. Use [`WebSocket::close`] for this.
39    /// Though the remote peer will likely close the connection after receiving this.
40    ///
41    /// [`WebSocket::close`]: crate::WebSocket::close
42    Close { code: CloseCode, reason: String },
43}
44
45impl From<String> for Message {
46    #[inline]
47    fn from(value: String) -> Self {
48        Self::Text(value)
49    }
50}
51
52impl From<&str> for Message {
53    #[inline]
54    fn from(value: &str) -> Self {
55        Self::from(value.to_owned())
56    }
57}
58
59impl From<Vec<u8>> for Message {
60    #[inline]
61    fn from(value: Vec<u8>) -> Self {
62        Self::Binary(value)
63    }
64}
65
66impl From<&[u8]> for Message {
67    #[inline]
68    fn from(value: &[u8]) -> Self {
69        Self::from(value.to_vec())
70    }
71}
72
73/// Status code used to indicate why an endpoint is closing the `WebSocket`
74/// connection.[1]
75///
76/// [1]: https://datatracker.ietf.org/doc/html/rfc6455
77#[derive(Debug, Default, Eq, PartialEq, Clone, Copy)]
78#[non_exhaustive]
79pub enum CloseCode {
80    /// Indicates a normal closure, meaning that the purpose for
81    /// which the connection was established has been fulfilled.
82    #[default]
83    Normal,
84
85    /// Indicates that an endpoint is "going away", such as a server
86    /// going down or a browser having navigated away from a page.
87    Away,
88
89    /// Indicates that an endpoint is terminating the connection due
90    /// to a protocol error.
91    Protocol,
92
93    /// Indicates that an endpoint is terminating the connection
94    /// because it has received a type of data it cannot accept (e.g., an
95    /// endpoint that understands only text data MAY send this if it
96    /// receives a binary message).
97    Unsupported,
98
99    /// Indicates that no status code was included in a closing frame. This
100    /// close code makes it possible to use a single method, `on_close` to
101    /// handle even cases where no close code was provided.
102    Status,
103
104    /// Indicates an abnormal closure. If the abnormal closure was due to an
105    /// error, this close code will not be used. Instead, the `on_error` method
106    /// of the handler will be called with the error. However, if the connection
107    /// is simply dropped, without an error, this close code will be sent to the
108    /// handler.
109    Abnormal,
110
111    /// Indicates that an endpoint is terminating the connection
112    /// because it has received data within a message that was not
113    /// consistent with the type of the message (e.g., non-UTF-8 \[RFC3629\]
114    /// data within a text message).
115    Invalid,
116
117    /// Indicates that an endpoint is terminating the connection
118    /// because it has received a message that violates its policy.  This
119    /// is a generic status code that can be returned when there is no
120    /// other more suitable status code (e.g., Unsupported or Size) or if there
121    /// is a need to hide specific details about the policy.
122    Policy,
123
124    /// Indicates that an endpoint is terminating the connection
125    /// because it has received a message that is too big for it to
126    /// process.
127    Size,
128
129    /// Indicates that an endpoint (client) is terminating the
130    /// connection because it has expected the server to negotiate one or
131    /// more extension, but the server didn't return them in the response
132    /// message of the `WebSocket` handshake.  The list of extensions that
133    /// are needed should be given as the reason for closing.
134    /// Note that this status code is not used by the server, because it
135    /// can fail the `WebSocket` handshake instead.
136    Extension,
137
138    /// Indicates that a server is terminating the connection because
139    /// it encountered an unexpected condition that prevented it from
140    /// fulfilling the request.
141    Error,
142
143    /// Indicates that the server is restarting. A client may choose to
144    /// reconnect, and if it does, it should use a randomized delay of 5-30
145    /// seconds between attempts.
146    Restart,
147
148    /// Indicates that the server is overloaded and the client should either
149    /// connect to a different IP (when multiple targets exist), or
150    /// reconnect to the same IP when a user has performed an action.
151    Again,
152
153    /// Indicates that the connection was closed due to a failure to perform a
154    /// TLS handshake (e.g., the server certificate can't be verified). This
155    /// is a reserved value and MUST NOT be set as a status code in a Close
156    /// control frame by an endpoint.
157    Tls,
158
159    /// Reserved status codes.
160    Reserved(u16),
161
162    /// Reserved for use by libraries, frameworks, and applications. These
163    /// status codes are registered directly with IANA. The interpretation of
164    /// these codes is undefined by the `WebSocket` protocol.
165    Iana(u16),
166
167    /// Reserved for private use. These can't be registered and can be used by
168    /// prior agreements between `WebSocket` applications. The interpretation of
169    /// these codes is undefined by the `WebSocket` protocol.
170    Library(u16),
171
172    /// Unused / invalid status codes.
173    Bad(u16),
174}
175
176impl CloseCode {
177    /// Check if this `CloseCode` is allowed.
178    #[must_use]
179    pub const fn is_allowed(self) -> bool {
180        !matches!(
181            self,
182            Self::Bad(_) | Self::Reserved(_) | Self::Status | Self::Abnormal | Self::Tls
183        )
184    }
185}
186
187impl std::fmt::Display for CloseCode {
188    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
189        let code: u16 = (*self).into();
190        write!(f, "{code}")
191    }
192}
193
194impl From<CloseCode> for u16 {
195    fn from(code: CloseCode) -> Self {
196        match code {
197            CloseCode::Normal => 1000,
198            CloseCode::Away => 1001,
199            CloseCode::Protocol => 1002,
200            CloseCode::Unsupported => 1003,
201            CloseCode::Status => 1005,
202            CloseCode::Abnormal => 1006,
203            CloseCode::Invalid => 1007,
204            CloseCode::Policy => 1008,
205            CloseCode::Size => 1009,
206            CloseCode::Extension => 1010,
207            CloseCode::Error => 1011,
208            CloseCode::Restart => 1012,
209            CloseCode::Again => 1013,
210            CloseCode::Tls => 1015,
211            CloseCode::Reserved(code)
212            | CloseCode::Iana(code)
213            | CloseCode::Library(code)
214            | CloseCode::Bad(code) => code,
215        }
216    }
217}
218
219impl From<u16> for CloseCode {
220    fn from(code: u16) -> Self {
221        match code {
222            1000 => Self::Normal,
223            1001 => Self::Away,
224            1002 => Self::Protocol,
225            1003 => Self::Unsupported,
226            1005 => Self::Status,
227            1006 => Self::Abnormal,
228            1007 => Self::Invalid,
229            1008 => Self::Policy,
230            1009 => Self::Size,
231            1010 => Self::Extension,
232            1011 => Self::Error,
233            1012 => Self::Restart,
234            1013 => Self::Again,
235            1015 => Self::Tls,
236            1016..=2999 => Self::Reserved(code),
237            3000..=3999 => Self::Iana(code),
238            4000..=4999 => Self::Library(code),
239            _ => Self::Bad(code),
240        }
241    }
242}