url_parse/core/
port.rs

1use regex::Regex;
2
3use crate::core::Parser;
4use crate::utils::Utils;
5
6impl Parser {
7    /// Extract the port from the url. If no port is present, it will be deduced from the scheme.
8    /// The default scheme provides well-known ports. The user can specify new schemes when constructing the Parser object with `new()`.
9    ///
10    /// # Example
11    /// ```rust
12    /// use url_parse::core::Parser;
13    /// let input = "https://www.example.co.uk:443/blog/article/search?docid=720&hl=en#dayone";
14    /// let port = Parser::new(None).port(input);
15    /// assert_eq!(port.unwrap(), 443);
16    /// ```
17    pub fn port(&self, input: &str) -> Option<u32> {
18        let rest = Utils::substring_after_login(self, input);
19        let position_colon = rest.find(':');
20        if let Some(v) = position_colon {
21            let _before = &rest[..v];
22            let after = &rest[v + 1..];
23            let re = Regex::new("^[0-9]+").unwrap();
24            let caps = re.captures(after);
25            caps.as_ref()?;
26            let caps = caps.unwrap();
27
28            return Some(caps.get(0).unwrap().as_str().trim().parse::<u32>().unwrap());
29        }
30
31        let default_port = match self.scheme(input) {
32            Some((v, _)) => {
33                let (port, _) = self.port_mappings[&v];
34                Some(port)
35            }
36            None => None,
37        };
38        default_port
39    }
40}
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45
46    #[test]
47    fn test_port_works_when_typical() {
48        let input = "https://www.example.co.uk:443/blog/article/search?docid=720&hl=en#dayone";
49        let port = Parser::new(None).port(input);
50        assert_eq!(port.unwrap(), 443);
51    }
52
53    #[test]
54    fn test_port_works_when_scheme_and_port_specified() {
55        let input = "ftp://127.0.0.1:21/test";
56        let port = Parser::new(None).port(input);
57        assert_eq!(port.unwrap(), 21);
58    }
59
60    #[test]
61    fn test_port_works_when_no_path() {
62        let input = "https://www.example.co.uk:443";
63        let port = Parser::new(None).port(input);
64        assert_eq!(port.unwrap(), 443);
65    }
66    #[test]
67    fn test_port_default_works_when_https() {
68        let input = "https://www.example.co.uk";
69        let port = Parser::new(None).port(input);
70        assert_eq!(port.unwrap(), 443);
71    }
72
73    #[test]
74    fn test_port_works_when_default_port_login_and_no_port() {
75        let input =
76            "https://user:pass@www.example.co.uk/blog/article/search?docid=720&hl=en#dayone";
77        let result = Parser::new(None).port(input).unwrap();
78        assert_eq!(result, 443);
79    }
80    #[test]
81    fn test_port_works_when_login_and_no_port() {
82        let input = "user:pass@www.example.co.uk/blog/article/search?docid=720&hl=en#dayone";
83        let result = Parser::new(None).port(input);
84        assert!(result.is_none());
85    }
86
87    #[test]
88    fn test_port_works_when_login_and_no_port_with_numbers() {
89        let input = "user:pass@www.example.co.uk/blog/article/720/test.txt";
90        let result = Parser::new(None).port(input);
91        assert!(result.is_none());
92    }
93
94    #[test]
95    fn test_port_works_when_colon_in_url() {
96        let input = "http://en.wikipedia.org/wiki/Template:Welcome";
97        let result = Parser::new(None).port(input);
98        assert!(result.is_none());
99    }
100}