1 use url::Url; 2 3 /// A trait to try to convert some type into a `Url`. 4 /// 5 /// This trait is "sealed", such that only types within reqwest can 6 /// implement it. 7 pub trait IntoUrl: IntoUrlSealed {} 8 9 impl IntoUrl for Url {} 10 impl IntoUrl for String {} 11 impl<'a> IntoUrl for &'a str {} 12 impl<'a> IntoUrl for &'a String {} 13 14 pub trait IntoUrlSealed { 15 // Besides parsing as a valid `Url`, the `Url` must be a valid 16 // `http::Uri`, in that it makes sense to use in a network request. into_url(self) -> crate::Result<Url>17 fn into_url(self) -> crate::Result<Url>; 18 as_str(&self) -> &str19 fn as_str(&self) -> &str; 20 } 21 22 impl IntoUrlSealed for Url { into_url(self) -> crate::Result<Url>23 fn into_url(self) -> crate::Result<Url> { 24 if self.has_host() { 25 Ok(self) 26 } else { 27 Err(crate::error::url_bad_scheme(self)) 28 } 29 } 30 as_str(&self) -> &str31 fn as_str(&self) -> &str { 32 self.as_ref() 33 } 34 } 35 36 impl<'a> IntoUrlSealed for &'a str { into_url(self) -> crate::Result<Url>37 fn into_url(self) -> crate::Result<Url> { 38 Url::parse(self).map_err(crate::error::builder)?.into_url() 39 } 40 as_str(&self) -> &str41 fn as_str(&self) -> &str { 42 self 43 } 44 } 45 46 impl<'a> IntoUrlSealed for &'a String { into_url(self) -> crate::Result<Url>47 fn into_url(self) -> crate::Result<Url> { 48 (&**self).into_url() 49 } 50 as_str(&self) -> &str51 fn as_str(&self) -> &str { 52 self.as_ref() 53 } 54 } 55 56 impl<'a> IntoUrlSealed for String { into_url(self) -> crate::Result<Url>57 fn into_url(self) -> crate::Result<Url> { 58 (&*self).into_url() 59 } 60 as_str(&self) -> &str61 fn as_str(&self) -> &str { 62 self.as_ref() 63 } 64 } 65 66 if_hyper! { 67 pub(crate) fn expect_uri(url: &Url) -> http::Uri { 68 url.as_str() 69 .parse() 70 .expect("a parsed Url should always be a valid Uri") 71 } 72 73 pub(crate) fn try_uri(url: &Url) -> Option<http::Uri> { 74 url.as_str().parse().ok() 75 } 76 } 77 78 #[cfg(test)] 79 mod tests { 80 use super::*; 81 82 #[test] into_url_file_scheme()83 fn into_url_file_scheme() { 84 let err = "file:///etc/hosts".into_url().unwrap_err(); 85 assert_eq!( 86 err.to_string(), 87 "builder error for url (file:///etc/hosts): URL scheme is not allowed" 88 ); 89 } 90 } 91