ws_framer/
url.rs

1#[derive(Debug, PartialEq)]
2/// Struct that stores parsed websocket url result
3///
4/// Example input:
5/// ws://localhost:321/dsa
6pub struct WsUrl<'a> {
7    pub host: &'a str,
8    pub ip: &'a str,
9    pub port: u16,
10
11    pub path: &'a str,
12    pub secure: bool,
13}
14
15impl WsUrl<'_> {
16    /// Parse ws url string
17    pub fn from_str<'a>(ws_url: &'a str) -> Option<WsUrl<'a>> {
18        let (secure, host_start_offset) = if ws_url.starts_with("ws://") {
19            (false, 5)
20        } else if ws_url.starts_with("wss://") {
21            (true, 6)
22        } else {
23            return None;
24        };
25
26        let mut host_end = None;
27        if let Some(ws_url) = ws_url.get(host_start_offset..) {
28            let chars = ws_url.char_indices();
29            for c in chars {
30                if c.1 == '/' {
31                    host_end = Some(c.0 + host_start_offset);
32                    break;
33                }
34            }
35        }
36
37        let host = ws_url.get(host_start_offset..host_end.unwrap_or(ws_url.len()))?;
38        let path = ws_url.get(host_end.unwrap_or(ws_url.len())..ws_url.len())?;
39        let path = if path.len() == 0 { "/" } else { path };
40
41        let mut host_split = host.split(':');
42        let ip = host_split.next()?;
43        let port = if let Some(port_str) = host_split.next() {
44            u16::from_str_radix(port_str, 10).ok()?
45        } else {
46            //default ports
47            match secure {
48                true => 443,
49                false => 80,
50            }
51        };
52
53        if host_split.count() > 0 {
54            return None;
55        }
56
57        Some(WsUrl {
58            host,
59            ip,
60            port,
61            path,
62            secure,
63        })
64    }
65}
66
67#[cfg(feature = "alloc")]
68#[derive(Debug, PartialEq)]
69pub struct WsUrlOwned {
70    pub host: alloc::string::String,
71    pub ip: alloc::string::String,
72    pub port: u16,
73
74    pub path: alloc::string::String,
75    pub secure: bool,
76}
77
78#[cfg(feature = "alloc")]
79impl WsUrlOwned {
80    pub fn new(ws_url: &WsUrl<'_>) -> Self {
81        use crate::alloc::string::ToString;
82
83        Self {
84            host: ws_url.host.to_string(),
85            ip: ws_url.ip.to_string(),
86            port: ws_url.port,
87            path: ws_url.path.to_string(),
88            secure: ws_url.secure,
89        }
90    }
91
92    pub fn as_ref<'a>(&'a self) -> WsUrl<'a> {
93        WsUrl {
94            host: &self.host,
95            ip: &self.ip,
96            port: self.port,
97            path: &self.path,
98            secure: self.secure,
99        }
100    }
101}
102
103#[cfg(test)]
104mod tests {
105    use super::*;
106
107    #[test]
108    fn validate_ws_url_parse() {
109        assert_eq!(
110            WsUrl::from_str("ws://127.0.0.1"),
111            Some(WsUrl {
112                host: "127.0.0.1",
113                ip: "127.0.0.1",
114                port: 80,
115                path: "/",
116                secure: false
117            })
118        );
119
120        assert_eq!(
121            WsUrl::from_str("wss://127.0.0.1"),
122            Some(WsUrl {
123                host: "127.0.0.1",
124                ip: "127.0.0.1",
125                port: 443,
126                path: "/",
127                secure: true
128            })
129        );
130
131        assert_eq!(
132            WsUrl::from_str("ws://127.0.0.1:4321"),
133            Some(WsUrl {
134                host: "127.0.0.1:4321",
135                ip: "127.0.0.1",
136                port: 4321,
137                path: "/",
138                secure: false
139            })
140        );
141
142        assert_eq!(
143            WsUrl::from_str("wss://127.0.0.1:4321"),
144            Some(WsUrl {
145                host: "127.0.0.1:4321",
146                ip: "127.0.0.1",
147                port: 4321,
148                path: "/",
149                secure: true
150            })
151        );
152
153        assert_eq!(
154            WsUrl::from_str("ws://127.0.0.1:4321/cxz/ewq"),
155            Some(WsUrl {
156                host: "127.0.0.1:4321",
157                ip: "127.0.0.1",
158                port: 4321,
159                path: "/cxz/ewq",
160                secure: false
161            })
162        );
163
164        assert_eq!(
165            WsUrl::from_str("wss://127.0.0.1:4321/cxz/ewq"),
166            Some(WsUrl {
167                host: "127.0.0.1:4321",
168                ip: "127.0.0.1",
169                port: 4321,
170                path: "/cxz/ewq",
171                secure: true
172            })
173        );
174
175        assert_eq!(
176            WsUrl::from_str("ws://127.0.0.1/cxz/ewq"),
177            Some(WsUrl {
178                host: "127.0.0.1",
179                ip: "127.0.0.1",
180                port: 80,
181                path: "/cxz/ewq",
182                secure: false
183            })
184        );
185
186        assert_eq!(
187            WsUrl::from_str("wss://127.0.0.1/cxz/ewq"),
188            Some(WsUrl {
189                host: "127.0.0.1",
190                ip: "127.0.0.1",
191                port: 443,
192                path: "/cxz/ewq",
193                secure: true
194            })
195        );
196
197        assert_eq!(WsUrl::from_str("ws://127.0.0.1:d123"), None);
198        assert_eq!(WsUrl::from_str("ws://127.0.0.1:123d"), None);
199
200        assert_eq!(WsUrl::from_str("wsc://127.0.0.1/cxz/ewq"), None);
201        assert_eq!(WsUrl::from_str("ws://127.0.0.1:4321:123/cxz/ewq"), None);
202    }
203}