cdk_http_client/ws/
error.rs1#[derive(Debug, thiserror::Error)]
5pub enum WsError {
6 #[error("transient WebSocket error: {0}")]
8 Transient(String),
9 #[error("WebSocket subscriptions are not supported: {0}")]
11 NotSupported(String),
12 #[error("terminal WebSocket error: {0}")]
14 Terminal(String),
15}
16
17#[cfg(not(target_arch = "wasm32"))]
18impl WsError {
19 pub(crate) fn from_tungstenite(error: tokio_tungstenite::tungstenite::Error) -> Self {
20 use tokio_tungstenite::tungstenite::Error;
21
22 let status = match &error {
23 Error::Http(response) => Some(response.status().as_u16()),
24 _ => None,
25 };
26 let message = error.to_string();
27
28 match status {
29 Some(404 | 405 | 501) => Self::NotSupported(message),
30 Some(408 | 429 | 500..=599) => Self::Transient(message),
31 Some(_) => Self::Terminal(message),
32 None => match error {
33 Error::ConnectionClosed | Error::AlreadyClosed | Error::Io(_) => {
34 Self::Transient(message)
35 }
36 Error::Tls(_)
37 | Error::Capacity(_)
38 | Error::Protocol(_)
39 | Error::WriteBufferFull(_)
40 | Error::Utf8
41 | Error::AttackAttempt
42 | Error::Url(_)
43 | Error::Http(_)
44 | Error::HttpFormat(_) => Self::Terminal(message),
45 },
46 }
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53
54 #[cfg(not(target_arch = "wasm32"))]
55 #[test]
56 fn classifies_http_upgrade_statuses() {
57 use tokio_tungstenite::tungstenite::http::{Response, StatusCode};
58 use tokio_tungstenite::tungstenite::Error;
59
60 let error_for_status = |status| {
61 Error::Http(
62 Response::builder()
63 .status(status)
64 .body(None)
65 .expect("valid HTTP response"),
66 )
67 };
68
69 assert!(matches!(
70 WsError::from_tungstenite(error_for_status(StatusCode::NOT_FOUND)),
71 WsError::NotSupported(_)
72 ));
73 assert!(matches!(
74 WsError::from_tungstenite(error_for_status(StatusCode::UNAUTHORIZED)),
75 WsError::Terminal(_)
76 ));
77 assert!(matches!(
78 WsError::from_tungstenite(error_for_status(StatusCode::SERVICE_UNAVAILABLE)),
79 WsError::Transient(_)
80 ));
81 }
82}