Skip to main content

http_request/request/socket/shared/
impl.rs

1use http_type::{HTTP_LOWERCASE, HTTP_UPPERCASE};
2
3use crate::*;
4
5impl std::fmt::Display for WebSocketError {
6    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
7        match self.kind {
8            WebSocketErrorKind::Connection => write!(f, "Connection error: {}", self.message),
9            WebSocketErrorKind::String => write!(f, "String error: {}", self.message),
10            WebSocketErrorKind::Timeout => write!(f, "Timeout error: {}", self.message),
11            WebSocketErrorKind::InvalidUrl => write!(f, "Invalid URL: {}", self.message),
12            WebSocketErrorKind::Io => write!(f, "IO error: {}", self.message),
13            WebSocketErrorKind::Tls => write!(f, "TLS error: {}", self.message),
14        }
15    }
16}
17
18impl std::error::Error for WebSocketError {}
19
20impl WebSocketError {
21    pub(crate) fn connection<T: ToString>(message: T) -> Self {
22        Self {
23            kind: WebSocketErrorKind::Connection,
24            message: message.to_string(),
25        }
26    }
27
28    pub(crate) fn protocol<T: ToString>(message: T) -> Self {
29        Self {
30            kind: WebSocketErrorKind::String,
31            message: message.to_string(),
32        }
33    }
34
35    pub(crate) fn timeout<T: ToString>(message: T) -> Self {
36        Self {
37            kind: WebSocketErrorKind::Timeout,
38            message: message.to_string(),
39        }
40    }
41
42    pub(crate) fn invalid_url<T: ToString>(message: T) -> Self {
43        Self {
44            kind: WebSocketErrorKind::InvalidUrl,
45            message: message.to_string(),
46        }
47    }
48
49    pub(crate) fn io<T: ToString>(message: T) -> Self {
50        Self {
51            kind: WebSocketErrorKind::Io,
52            message: message.to_string(),
53        }
54    }
55
56    pub(crate) fn tls<T: ToString>(message: T) -> Self {
57        Self {
58            kind: WebSocketErrorKind::Tls,
59            message: message.to_string(),
60        }
61    }
62}
63
64impl SharedWebSocketBuilder {
65    pub(crate) fn parse_url(url: &str) -> Result<HttpUrlComponents, WebSocketError> {
66        if url.is_empty() {
67            return Err(WebSocketError::invalid_url("URL is empty"));
68        }
69        let mut url_obj: HttpUrlComponents = HttpUrlComponents::default();
70        if url.starts_with("ws://") {
71            url_obj.protocol = HTTP_LOWERCASE.to_string();
72            url_obj.port = Some(80);
73        } else if url.starts_with("wss://") {
74            url_obj.protocol = HTTP_UPPERCASE.to_string();
75            url_obj.port = Some(443);
76        } else {
77            return Err(WebSocketError::invalid_url("Invalid WebSocket URL scheme"));
78        }
79        let without_protocol: &str = if let Some(stripped) = url.strip_prefix("ws://") {
80            stripped
81        } else {
82            &url[6..]
83        };
84        let parts: Vec<&str> = without_protocol.splitn(2, '/').collect();
85        let host_port: &str = parts[0];
86        let path: &str = if parts.len() > 1 { parts[1] } else { "" };
87        if host_port.contains(':') {
88            let host_port_parts: Vec<&str> = host_port.splitn(2, ':').collect();
89            url_obj.host = Some(host_port_parts[0].to_string());
90            if let Ok(port) = host_port_parts[1].parse::<u16>() {
91                url_obj.port = Some(port);
92            }
93        } else {
94            url_obj.host = Some(host_port.to_string());
95        }
96        url_obj.path = Some(if path.is_empty() {
97            "/".to_string()
98        } else {
99            format!("/{path}")
100        });
101        Ok(url_obj)
102    }
103}