Skip to main content

oxihttp_core/
uri_ext.rs

1//! URI extension methods.
2
3use http::Uri;
4
5/// Extension trait providing convenience methods for `http::Uri`.
6pub trait UriExt {
7    /// Extract the host from the URI.
8    fn host_str(&self) -> Option<&str>;
9
10    /// Return the port, or the default port for the scheme (80 for HTTP, 443 for HTTPS).
11    fn port_or_default(&self) -> Option<u16>;
12
13    /// Returns `true` if the URI scheme is `https`.
14    fn is_https(&self) -> bool;
15
16    /// Returns `true` if the URI scheme is `http`.
17    fn is_http(&self) -> bool;
18
19    /// Return the origin portion of the URI (scheme + authority).
20    fn origin(&self) -> Option<String>;
21}
22
23impl UriExt for Uri {
24    fn host_str(&self) -> Option<&str> {
25        self.host()
26    }
27
28    fn port_or_default(&self) -> Option<u16> {
29        if let Some(port) = self.port_u16() {
30            return Some(port);
31        }
32        match self.scheme_str() {
33            Some("https") => Some(443),
34            Some("http") => Some(80),
35            _ => None,
36        }
37    }
38
39    fn is_https(&self) -> bool {
40        self.scheme_str() == Some("https")
41    }
42
43    fn is_http(&self) -> bool {
44        self.scheme_str() == Some("http")
45    }
46
47    fn origin(&self) -> Option<String> {
48        let scheme = self.scheme_str()?;
49        let authority = self.authority()?.as_str();
50        Some(format!("{scheme}://{authority}"))
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57    use std::str::FromStr;
58
59    #[test]
60    fn test_host() {
61        let uri = Uri::from_str("http://example.com/path").expect("parse");
62        assert_eq!(uri.host_str(), Some("example.com"));
63    }
64
65    #[test]
66    fn test_port_or_default_http() {
67        let uri = Uri::from_str("http://example.com/path").expect("parse");
68        assert_eq!(uri.port_or_default(), Some(80));
69    }
70
71    #[test]
72    fn test_port_or_default_https() {
73        let uri = Uri::from_str("https://example.com/path").expect("parse");
74        assert_eq!(uri.port_or_default(), Some(443));
75    }
76
77    #[test]
78    fn test_port_or_default_explicit() {
79        let uri = Uri::from_str("http://example.com:8080/path").expect("parse");
80        assert_eq!(uri.port_or_default(), Some(8080));
81    }
82
83    #[test]
84    fn test_is_https() {
85        let uri = Uri::from_str("https://example.com").expect("parse");
86        assert!(uri.is_https());
87        assert!(!uri.is_http());
88    }
89
90    #[test]
91    fn test_is_http() {
92        let uri = Uri::from_str("http://example.com").expect("parse");
93        assert!(uri.is_http());
94        assert!(!uri.is_https());
95    }
96
97    #[test]
98    fn test_origin() {
99        let uri = Uri::from_str("https://example.com:8443/path?q=1").expect("parse");
100        assert_eq!(uri.origin(), Some("https://example.com:8443".to_string()));
101    }
102
103    #[test]
104    fn test_no_scheme() {
105        let uri = Uri::from_str("/path/only").expect("parse");
106        assert_eq!(uri.port_or_default(), None);
107        assert!(!uri.is_http());
108        assert!(!uri.is_https());
109        assert!(uri.origin().is_none());
110    }
111}