Skip to main content

tower_http_client/client/
into_uri.rs

1use http::{Uri, uri};
2use private::Sealed;
3
4/// A helper trait to try to convert some types into `Uri`.
5///
6/// This trait is sealed and implemented only for the most suitable types.
7///
8/// Unlike the similar trait in the Reqwest, this one describes a type's representation
9/// that implements [`TryInto<Uri>`]. This approach can pass third-party types like `url::Url`
10/// directly to the [`http::request::Builder::uri`] without any wrappers.
11pub trait IntoUri: Sealed {
12    /// Which kind of value should be converted to the Uri via [`TryInto<Uri>`]
13    type TryInto;
14    /// Converts this value into the input type for the [`TryInto<Uri>`] conversion.
15    fn into_uri(self) -> Self::TryInto;
16}
17
18impl IntoUri for &Uri {
19    type TryInto = Self;
20
21    fn into_uri(self) -> Self::TryInto {
22        self
23    }
24}
25
26impl IntoUri for Uri {
27    type TryInto = Self;
28
29    fn into_uri(self) -> Self::TryInto {
30        self
31    }
32}
33
34impl IntoUri for String {
35    type TryInto = Self;
36
37    fn into_uri(self) -> Self::TryInto {
38        self
39    }
40}
41
42impl IntoUri for &String {
43    type TryInto = Self;
44
45    fn into_uri(self) -> Self::TryInto {
46        self
47    }
48}
49
50impl IntoUri for &str {
51    type TryInto = Self;
52
53    fn into_uri(self) -> Self::TryInto {
54        self
55    }
56}
57
58impl<'a> IntoUri for &'a Vec<u8> {
59    type TryInto = &'a [u8];
60
61    fn into_uri(self) -> Self::TryInto {
62        self
63    }
64}
65
66impl IntoUri for Vec<u8> {
67    type TryInto = Self;
68
69    fn into_uri(self) -> Self::TryInto {
70        self
71    }
72}
73
74impl IntoUri for &[u8] {
75    type TryInto = Self;
76
77    fn into_uri(self) -> Self::TryInto {
78        self
79    }
80}
81
82impl IntoUri for uri::Parts {
83    type TryInto = Self;
84
85    fn into_uri(self) -> Self::TryInto {
86        self
87    }
88}
89
90#[cfg(feature = "url")]
91impl IntoUri for url::Url {
92    type TryInto = String;
93
94    fn into_uri(self) -> Self::TryInto {
95        self.into()
96    }
97}
98
99#[cfg(feature = "url")]
100impl<'a> IntoUri for &'a url::Url {
101    type TryInto = &'a str;
102
103    fn into_uri(self) -> Self::TryInto {
104        self.as_str()
105    }
106}
107
108mod private {
109    use http::{Uri, uri};
110    #[cfg(feature = "url")]
111    use url::Url;
112
113    pub trait Sealed {}
114
115    impl Sealed for uri::Parts {}
116    impl Sealed for Uri {}
117    impl Sealed for &Uri {}
118
119    impl Sealed for String {}
120    impl Sealed for &String {}
121    impl Sealed for &str {}
122
123    impl Sealed for Vec<u8> {}
124    impl Sealed for &Vec<u8> {}
125    impl Sealed for &[u8] {}
126
127    #[cfg(feature = "url")]
128    impl Sealed for Url {}
129    #[cfg(feature = "url")]
130    impl Sealed for &Url {}
131}
132
133#[cfg(feature = "url")]
134#[cfg(test)]
135mod tests {
136    use http::Uri;
137    use url::Url;
138
139    use super::IntoUri as _;
140
141    #[test]
142    fn test_url_to_uri_smoke() {
143        let example =
144            "abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1";
145
146        let url = Url::parse(example).unwrap();
147        let expected_uri = Uri::from_static(example);
148
149        let actual_uri: Uri = url.into_uri().parse().expect("failed to convert url");
150        assert_eq!(actual_uri, expected_uri);
151    }
152}