Skip to main content

specter/websocket/
error.rs

1use std::io;
2
3pub type WebSocketResult<T> = std::result::Result<T, WebSocketError>;
4
5#[derive(Debug, thiserror::Error)]
6pub enum WebSocketError {
7    #[error("WebSocket handshake failed for {url}: expected status 101, got {status}")]
8    InvalidStatus { url: String, status: u16 },
9
10    #[error("WebSocket handshake failed for {url}: invalid Sec-WebSocket-Accept")]
11    InvalidAccept { url: String },
12
13    #[error("WebSocket handshake failed for {url}: unexpected subprotocol")]
14    UnexpectedSubprotocol { url: String },
15
16    #[error("WebSocket handshake failed for {url}: unexpected extension")]
17    UnexpectedExtension { url: String },
18
19    #[error("WebSocket protocol error for {url}: {message}")]
20    Protocol { url: String, message: String },
21
22    #[error("WebSocket UTF-8 error for {url}: {message}")]
23    Utf8 { url: String, message: String },
24
25    #[error("WebSocket size limit exceeded for {url}: {message}")]
26    LimitExceeded { url: String, message: String },
27
28    #[error("WebSocket connection closed for {url}")]
29    ConnectionClosed { url: String },
30
31    #[error("WebSocket timeout for {url}: {operation}")]
32    Timeout { url: String, operation: String },
33
34    #[error("WebSocket I/O error for {url}: {source}")]
35    Io {
36        url: String,
37        #[source]
38        source: io::Error,
39    },
40
41    #[error("WebSocket URL error: {0}")]
42    Url(#[from] url::ParseError),
43}
44
45impl WebSocketError {
46    pub(crate) fn protocol(url: &url::Url, message: impl Into<String>) -> Self {
47        Self::Protocol {
48            url: url.to_string(),
49            message: message.into(),
50        }
51    }
52
53    pub(crate) fn utf8(url: &url::Url, message: impl Into<String>) -> Self {
54        Self::Utf8 {
55            url: url.to_string(),
56            message: message.into(),
57        }
58    }
59
60    pub(crate) fn limit_exceeded(url: &url::Url, message: impl Into<String>) -> Self {
61        Self::LimitExceeded {
62            url: url.to_string(),
63            message: message.into(),
64        }
65    }
66
67    pub(crate) fn connection_closed(url: &url::Url) -> Self {
68        Self::ConnectionClosed {
69            url: url.to_string(),
70        }
71    }
72
73    pub(crate) fn io(url: &url::Url, source: io::Error) -> Self {
74        Self::Io {
75            url: url.to_string(),
76            source,
77        }
78    }
79
80    pub(crate) fn close_code(&self) -> Option<crate::websocket::CloseCode> {
81        match self {
82            Self::Protocol { .. } => Some(crate::websocket::CloseCode::Protocol),
83            Self::Utf8 { .. } => Some(crate::websocket::CloseCode::Invalid),
84            Self::LimitExceeded { .. } => Some(crate::websocket::CloseCode::Size),
85            _ => None,
86        }
87    }
88}