diff options
Diffstat (limited to 'vendor/http/src/uri')
| -rw-r--r-- | vendor/http/src/uri/authority.rs | 684 | ||||
| -rw-r--r-- | vendor/http/src/uri/builder.rs | 211 | ||||
| -rw-r--r-- | vendor/http/src/uri/mod.rs | 1117 | ||||
| -rw-r--r-- | vendor/http/src/uri/path.rs | 604 | ||||
| -rw-r--r-- | vendor/http/src/uri/port.rs | 151 | ||||
| -rw-r--r-- | vendor/http/src/uri/scheme.rs | 361 | ||||
| -rw-r--r-- | vendor/http/src/uri/tests.rs | 519 |
7 files changed, 0 insertions, 3647 deletions
diff --git a/vendor/http/src/uri/authority.rs b/vendor/http/src/uri/authority.rs deleted file mode 100644 index 07aa6795..00000000 --- a/vendor/http/src/uri/authority.rs +++ /dev/null @@ -1,684 +0,0 @@ -use std::convert::TryFrom; -use std::hash::{Hash, Hasher}; -use std::str::FromStr; -use std::{cmp, fmt, str}; - -use bytes::Bytes; - -use super::{ErrorKind, InvalidUri, Port, URI_CHARS}; -use crate::byte_str::ByteStr; - -/// Represents the authority component of a URI. -#[derive(Clone)] -pub struct Authority { - pub(super) data: ByteStr, -} - -impl Authority { - pub(super) fn empty() -> Self { - Authority { - data: ByteStr::new(), - } - } - - // Not public while `bytes` is unstable. - pub(super) fn from_shared(s: Bytes) -> Result<Self, InvalidUri> { - // Precondition on create_authority: trivially satisfied by the - // identity closure - create_authority(s, |s| s) - } - - /// Attempt to convert an `Authority` from a static string. - /// - /// This function will not perform any copying, and the string will be - /// checked if it is empty or contains an invalid character. - /// - /// # Panics - /// - /// This function panics if the argument contains invalid characters or - /// is empty. - /// - /// # Examples - /// - /// ``` - /// # use http::uri::Authority; - /// let authority = Authority::from_static("example.com"); - /// assert_eq!(authority.host(), "example.com"); - /// ``` - pub fn from_static(src: &'static str) -> Self { - Authority::from_shared(Bytes::from_static(src.as_bytes())) - .expect("static str is not valid authority") - } - - /// Attempt to convert a `Bytes` buffer to a `Authority`. - /// - /// This will try to prevent a copy if the type passed is the type used - /// internally, and will copy the data if it is not. - pub fn from_maybe_shared<T>(src: T) -> Result<Self, InvalidUri> - where - T: AsRef<[u8]> + 'static, - { - if_downcast_into!(T, Bytes, src, { - return Authority::from_shared(src); - }); - - Authority::try_from(src.as_ref()) - } - - // Note: this may return an *empty* Authority. You might want `parse_non_empty`. - // Postcondition: for all Ok() returns, s[..ret.unwrap()] is valid UTF-8 where - // ret is the return value. - pub(super) fn parse(s: &[u8]) -> Result<usize, InvalidUri> { - let mut colon_cnt = 0u32; - let mut start_bracket = false; - let mut end_bracket = false; - let mut has_percent = false; - let mut end = s.len(); - let mut at_sign_pos = None; - const MAX_COLONS: u32 = 8; // e.g., [FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80 - - // Among other things, this loop checks that every byte in s up to the - // first '/', '?', or '#' is a valid URI character (or in some contexts, - // a '%'). This means that each such byte is a valid single-byte UTF-8 - // code point. - for (i, &b) in s.iter().enumerate() { - match URI_CHARS[b as usize] { - b'/' | b'?' | b'#' => { - end = i; - break; - } - b':' => { - if colon_cnt >= MAX_COLONS { - return Err(ErrorKind::InvalidAuthority.into()); - } - colon_cnt += 1; - } - b'[' => { - if has_percent || start_bracket { - // Something other than the userinfo has a `%`, so reject it. - return Err(ErrorKind::InvalidAuthority.into()); - } - start_bracket = true; - } - b']' => { - if (!start_bracket) || end_bracket { - return Err(ErrorKind::InvalidAuthority.into()); - } - end_bracket = true; - - // Those were part of an IPv6 hostname, so forget them... - colon_cnt = 0; - has_percent = false; - } - b'@' => { - at_sign_pos = Some(i); - - // Those weren't a port colon, but part of the - // userinfo, so it needs to be forgotten. - colon_cnt = 0; - has_percent = false; - } - 0 if b == b'%' => { - // Per https://tools.ietf.org/html/rfc3986#section-3.2.1 and - // https://url.spec.whatwg.org/#authority-state - // the userinfo can have a percent-encoded username and password, - // so record that a `%` was found. If this turns out to be - // part of the userinfo, this flag will be cleared. - // Also per https://tools.ietf.org/html/rfc6874, percent-encoding can - // be used to indicate a zone identifier. - // If the flag hasn't been cleared at the end, that means this - // was part of the hostname (and not part of an IPv6 address), and - // will fail with an error. - has_percent = true; - } - 0 => { - return Err(ErrorKind::InvalidUriChar.into()); - } - _ => {} - } - } - - if start_bracket ^ end_bracket { - return Err(ErrorKind::InvalidAuthority.into()); - } - - if colon_cnt > 1 { - // Things like 'localhost:8080:3030' are rejected. - return Err(ErrorKind::InvalidAuthority.into()); - } - - if end > 0 && at_sign_pos == Some(end - 1) { - // If there's nothing after an `@`, this is bonkers. - return Err(ErrorKind::InvalidAuthority.into()); - } - - if has_percent { - // Something after the userinfo has a `%`, so reject it. - return Err(ErrorKind::InvalidAuthority.into()); - } - - Ok(end) - } - - // Parse bytes as an Authority, not allowing an empty string. - // - // This should be used by functions that allow a user to parse - // an `Authority` by itself. - // - // Postcondition: for all Ok() returns, s[..ret.unwrap()] is valid UTF-8 where - // ret is the return value. - fn parse_non_empty(s: &[u8]) -> Result<usize, InvalidUri> { - if s.is_empty() { - return Err(ErrorKind::Empty.into()); - } - Authority::parse(s) - } - - /// Get the host of this `Authority`. - /// - /// The host subcomponent of authority is identified by an IP literal - /// encapsulated within square brackets, an IPv4 address in dotted- decimal - /// form, or a registered name. The host subcomponent is **case-insensitive**. - /// - /// ```notrust - /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1 - /// |---------| - /// | - /// host - /// ``` - /// - /// # Examples - /// - /// ``` - /// # use http::uri::*; - /// let authority: Authority = "example.org:80".parse().unwrap(); - /// - /// assert_eq!(authority.host(), "example.org"); - /// ``` - #[inline] - pub fn host(&self) -> &str { - host(self.as_str()) - } - - /// Get the port part of this `Authority`. - /// - /// The port subcomponent of authority is designated by an optional port - /// number following the host and delimited from it by a single colon (":") - /// character. It can be turned into a decimal port number with the `as_u16` - /// method or as a `str` with the `as_str` method. - /// - /// ```notrust - /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1 - /// |-| - /// | - /// port - /// ``` - /// - /// # Examples - /// - /// Authority with port - /// - /// ``` - /// # use http::uri::Authority; - /// let authority: Authority = "example.org:80".parse().unwrap(); - /// - /// let port = authority.port().unwrap(); - /// assert_eq!(port.as_u16(), 80); - /// assert_eq!(port.as_str(), "80"); - /// ``` - /// - /// Authority without port - /// - /// ``` - /// # use http::uri::Authority; - /// let authority: Authority = "example.org".parse().unwrap(); - /// - /// assert!(authority.port().is_none()); - /// ``` - pub fn port(&self) -> Option<Port<&str>> { - let bytes = self.as_str(); - bytes - .rfind(':') - .and_then(|i| Port::from_str(&bytes[i + 1..]).ok()) - } - - /// Get the port of this `Authority` as a `u16`. - /// - /// # Example - /// - /// ``` - /// # use http::uri::Authority; - /// let authority: Authority = "example.org:80".parse().unwrap(); - /// - /// assert_eq!(authority.port_u16(), Some(80)); - /// ``` - pub fn port_u16(&self) -> Option<u16> { - self.port().map(|p| p.as_u16()) - } - - /// Return a str representation of the authority - #[inline] - pub fn as_str(&self) -> &str { - &self.data[..] - } -} - -// Purposefully not public while `bytes` is unstable. -// impl TryFrom<Bytes> for Authority - -impl AsRef<str> for Authority { - fn as_ref(&self) -> &str { - self.as_str() - } -} - -impl PartialEq for Authority { - fn eq(&self, other: &Authority) -> bool { - self.data.eq_ignore_ascii_case(&other.data) - } -} - -impl Eq for Authority {} - -/// Case-insensitive equality -/// -/// # Examples -/// -/// ``` -/// # use http::uri::Authority; -/// let authority: Authority = "HELLO.com".parse().unwrap(); -/// assert_eq!(authority, "hello.coM"); -/// assert_eq!("hello.com", authority); -/// ``` -impl PartialEq<str> for Authority { - fn eq(&self, other: &str) -> bool { - self.data.eq_ignore_ascii_case(other) - } -} - -impl PartialEq<Authority> for str { - fn eq(&self, other: &Authority) -> bool { - self.eq_ignore_ascii_case(other.as_str()) - } -} - -impl<'a> PartialEq<Authority> for &'a str { - fn eq(&self, other: &Authority) -> bool { - self.eq_ignore_ascii_case(other.as_str()) - } -} - -impl<'a> PartialEq<&'a str> for Authority { - fn eq(&self, other: &&'a str) -> bool { - self.data.eq_ignore_ascii_case(other) - } -} - -impl PartialEq<String> for Authority { - fn eq(&self, other: &String) -> bool { - self.data.eq_ignore_ascii_case(other.as_str()) - } -} - -impl PartialEq<Authority> for String { - fn eq(&self, other: &Authority) -> bool { - self.as_str().eq_ignore_ascii_case(other.as_str()) - } -} - -/// Case-insensitive ordering -/// -/// # Examples -/// -/// ``` -/// # use http::uri::Authority; -/// let authority: Authority = "DEF.com".parse().unwrap(); -/// assert!(authority < "ghi.com"); -/// assert!(authority > "abc.com"); -/// ``` -impl PartialOrd for Authority { - fn partial_cmp(&self, other: &Authority) -> Option<cmp::Ordering> { - let left = self.data.as_bytes().iter().map(|b| b.to_ascii_lowercase()); - let right = other.data.as_bytes().iter().map(|b| b.to_ascii_lowercase()); - left.partial_cmp(right) - } -} - -impl PartialOrd<str> for Authority { - fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> { - let left = self.data.as_bytes().iter().map(|b| b.to_ascii_lowercase()); - let right = other.as_bytes().iter().map(|b| b.to_ascii_lowercase()); - left.partial_cmp(right) - } -} - -impl PartialOrd<Authority> for str { - fn partial_cmp(&self, other: &Authority) -> Option<cmp::Ordering> { - let left = self.as_bytes().iter().map(|b| b.to_ascii_lowercase()); - let right = other.data.as_bytes().iter().map(|b| b.to_ascii_lowercase()); - left.partial_cmp(right) - } -} - -impl<'a> PartialOrd<Authority> for &'a str { - fn partial_cmp(&self, other: &Authority) -> Option<cmp::Ordering> { - let left = self.as_bytes().iter().map(|b| b.to_ascii_lowercase()); - let right = other.data.as_bytes().iter().map(|b| b.to_ascii_lowercase()); - left.partial_cmp(right) - } -} - -impl<'a> PartialOrd<&'a str> for Authority { - fn partial_cmp(&self, other: &&'a str) -> Option<cmp::Ordering> { - let left = self.data.as_bytes().iter().map(|b| b.to_ascii_lowercase()); - let right = other.as_bytes().iter().map(|b| b.to_ascii_lowercase()); - left.partial_cmp(right) - } -} - -impl PartialOrd<String> for Authority { - fn partial_cmp(&self, other: &String) -> Option<cmp::Ordering> { - let left = self.data.as_bytes().iter().map(|b| b.to_ascii_lowercase()); - let right = other.as_bytes().iter().map(|b| b.to_ascii_lowercase()); - left.partial_cmp(right) - } -} - -impl PartialOrd<Authority> for String { - fn partial_cmp(&self, other: &Authority) -> Option<cmp::Ordering> { - let left = self.as_bytes().iter().map(|b| b.to_ascii_lowercase()); - let right = other.data.as_bytes().iter().map(|b| b.to_ascii_lowercase()); - left.partial_cmp(right) - } -} - -/// Case-insensitive hashing -/// -/// # Examples -/// -/// ``` -/// # use http::uri::Authority; -/// # use std::hash::{Hash, Hasher}; -/// # use std::collections::hash_map::DefaultHasher; -/// -/// let a: Authority = "HELLO.com".parse().unwrap(); -/// let b: Authority = "hello.coM".parse().unwrap(); -/// -/// let mut s = DefaultHasher::new(); -/// a.hash(&mut s); -/// let a = s.finish(); -/// -/// let mut s = DefaultHasher::new(); -/// b.hash(&mut s); -/// let b = s.finish(); -/// -/// assert_eq!(a, b); -/// ``` -impl Hash for Authority { - fn hash<H>(&self, state: &mut H) - where - H: Hasher, - { - self.data.len().hash(state); - for &b in self.data.as_bytes() { - state.write_u8(b.to_ascii_lowercase()); - } - } -} - -impl<'a> TryFrom<&'a [u8]> for Authority { - type Error = InvalidUri; - #[inline] - fn try_from(s: &'a [u8]) -> Result<Self, Self::Error> { - // parse first, and only turn into Bytes if valid - - // Preconditon on create_authority: copy_from_slice() copies all of - // bytes from the [u8] parameter into a new Bytes - create_authority(s, Bytes::copy_from_slice) - } -} - -impl<'a> TryFrom<&'a str> for Authority { - type Error = InvalidUri; - #[inline] - fn try_from(s: &'a str) -> Result<Self, Self::Error> { - TryFrom::try_from(s.as_bytes()) - } -} - -impl TryFrom<Vec<u8>> for Authority { - type Error = InvalidUri; - - #[inline] - fn try_from(vec: Vec<u8>) -> Result<Self, Self::Error> { - Authority::from_shared(vec.into()) - } -} - -impl TryFrom<String> for Authority { - type Error = InvalidUri; - - #[inline] - fn try_from(t: String) -> Result<Self, Self::Error> { - Authority::from_shared(t.into()) - } -} - -impl FromStr for Authority { - type Err = InvalidUri; - - fn from_str(s: &str) -> Result<Self, InvalidUri> { - TryFrom::try_from(s) - } -} - -impl fmt::Debug for Authority { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(self.as_str()) - } -} - -impl fmt::Display for Authority { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(self.as_str()) - } -} - -fn host(auth: &str) -> &str { - let host_port = auth - .rsplit('@') - .next() - .expect("split always has at least 1 item"); - - if host_port.as_bytes()[0] == b'[' { - let i = host_port - .find(']') - .expect("parsing should validate brackets"); - // ..= ranges aren't available in 1.20, our minimum Rust version... - &host_port[0..i + 1] - } else { - host_port - .split(':') - .next() - .expect("split always has at least 1 item") - } -} - -// Precondition: f converts all of the bytes in the passed in B into the -// returned Bytes. -fn create_authority<B, F>(b: B, f: F) -> Result<Authority, InvalidUri> -where - B: AsRef<[u8]>, - F: FnOnce(B) -> Bytes, -{ - let s = b.as_ref(); - let authority_end = Authority::parse_non_empty(s)?; - - if authority_end != s.len() { - return Err(ErrorKind::InvalidUriChar.into()); - } - - let bytes = f(b); - - Ok(Authority { - // Safety: the postcondition on parse_non_empty() and the check against - // s.len() ensure that b is valid UTF-8. The precondition on f ensures - // that this is carried through to bytes. - data: unsafe { ByteStr::from_utf8_unchecked(bytes) }, - }) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn parse_empty_string_is_error() { - let err = Authority::parse_non_empty(b"").unwrap_err(); - assert_eq!(err.0, ErrorKind::Empty); - } - - #[test] - fn equal_to_self_of_same_authority() { - let authority1: Authority = "example.com".parse().unwrap(); - let authority2: Authority = "EXAMPLE.COM".parse().unwrap(); - assert_eq!(authority1, authority2); - assert_eq!(authority2, authority1); - } - - #[test] - fn not_equal_to_self_of_different_authority() { - let authority1: Authority = "example.com".parse().unwrap(); - let authority2: Authority = "test.com".parse().unwrap(); - assert_ne!(authority1, authority2); - assert_ne!(authority2, authority1); - } - - #[test] - fn equates_with_a_str() { - let authority: Authority = "example.com".parse().unwrap(); - assert_eq!(&authority, "EXAMPLE.com"); - assert_eq!("EXAMPLE.com", &authority); - assert_eq!(authority, "EXAMPLE.com"); - assert_eq!("EXAMPLE.com", authority); - } - - #[test] - fn from_static_equates_with_a_str() { - let authority = Authority::from_static("example.com"); - assert_eq!(authority, "example.com"); - } - - #[test] - fn not_equal_with_a_str_of_a_different_authority() { - let authority: Authority = "example.com".parse().unwrap(); - assert_ne!(&authority, "test.com"); - assert_ne!("test.com", &authority); - assert_ne!(authority, "test.com"); - assert_ne!("test.com", authority); - } - - #[test] - fn equates_with_a_string() { - let authority: Authority = "example.com".parse().unwrap(); - assert_eq!(authority, "EXAMPLE.com".to_string()); - assert_eq!("EXAMPLE.com".to_string(), authority); - } - - #[test] - fn equates_with_a_string_of_a_different_authority() { - let authority: Authority = "example.com".parse().unwrap(); - assert_ne!(authority, "test.com".to_string()); - assert_ne!("test.com".to_string(), authority); - } - - #[test] - fn compares_to_self() { - let authority1: Authority = "abc.com".parse().unwrap(); - let authority2: Authority = "def.com".parse().unwrap(); - assert!(authority1 < authority2); - assert!(authority2 > authority1); - } - - #[test] - fn compares_with_a_str() { - let authority: Authority = "def.com".parse().unwrap(); - // with ref - assert!(&authority < "ghi.com"); - assert!("ghi.com" > &authority); - assert!(&authority > "abc.com"); - assert!("abc.com" < &authority); - - // no ref - assert!(authority < "ghi.com"); - assert!("ghi.com" > authority); - assert!(authority > "abc.com"); - assert!("abc.com" < authority); - } - - #[test] - fn compares_with_a_string() { - let authority: Authority = "def.com".parse().unwrap(); - assert!(authority < "ghi.com".to_string()); - assert!("ghi.com".to_string() > authority); - assert!(authority > "abc.com".to_string()); - assert!("abc.com".to_string() < authority); - } - - #[test] - fn allows_percent_in_userinfo() { - let authority_str = "a%2f:b%2f@example.com"; - let authority: Authority = authority_str.parse().unwrap(); - assert_eq!(authority, authority_str); - } - - #[test] - fn rejects_percent_in_hostname() { - let err = Authority::parse_non_empty(b"example%2f.com").unwrap_err(); - assert_eq!(err.0, ErrorKind::InvalidAuthority); - - let err = Authority::parse_non_empty(b"a%2f:b%2f@example%2f.com").unwrap_err(); - assert_eq!(err.0, ErrorKind::InvalidAuthority); - } - - #[test] - fn allows_percent_in_ipv6_address() { - let authority_str = "[fe80::1:2:3:4%25eth0]"; - let result: Authority = authority_str.parse().unwrap(); - assert_eq!(result, authority_str); - } - - #[test] - fn reject_obviously_invalid_ipv6_address() { - let err = Authority::parse_non_empty(b"[0:1:2:3:4:5:6:7:8:9:10:11:12:13:14]").unwrap_err(); - assert_eq!(err.0, ErrorKind::InvalidAuthority); - } - - #[test] - fn rejects_percent_outside_ipv6_address() { - let err = Authority::parse_non_empty(b"1234%20[fe80::1:2:3:4]").unwrap_err(); - assert_eq!(err.0, ErrorKind::InvalidAuthority); - - let err = Authority::parse_non_empty(b"[fe80::1:2:3:4]%20").unwrap_err(); - assert_eq!(err.0, ErrorKind::InvalidAuthority); - } - - #[test] - fn rejects_invalid_utf8() { - let err = Authority::try_from([0xc0u8].as_ref()).unwrap_err(); - assert_eq!(err.0, ErrorKind::InvalidUriChar); - - let err = Authority::from_shared(Bytes::from_static([0xc0u8].as_ref())).unwrap_err(); - assert_eq!(err.0, ErrorKind::InvalidUriChar); - } - - #[test] - fn rejects_invalid_use_of_brackets() { - let err = Authority::parse_non_empty(b"[]@[").unwrap_err(); - assert_eq!(err.0, ErrorKind::InvalidAuthority); - - // reject tie-fighter - let err = Authority::parse_non_empty(b"]o[").unwrap_err(); - assert_eq!(err.0, ErrorKind::InvalidAuthority); - } -} diff --git a/vendor/http/src/uri/builder.rs b/vendor/http/src/uri/builder.rs deleted file mode 100644 index d5f7f49b..00000000 --- a/vendor/http/src/uri/builder.rs +++ /dev/null @@ -1,211 +0,0 @@ -use std::convert::TryInto; - -use super::{Authority, Parts, PathAndQuery, Scheme}; -use crate::Uri; - -/// A builder for `Uri`s. -/// -/// This type can be used to construct an instance of `Uri` -/// through a builder pattern. -#[derive(Debug)] -pub struct Builder { - parts: Result<Parts, crate::Error>, -} - -impl Builder { - /// Creates a new default instance of `Builder` to construct a `Uri`. - /// - /// # Examples - /// - /// ``` - /// # use http::*; - /// - /// let uri = uri::Builder::new() - /// .scheme("https") - /// .authority("hyper.rs") - /// .path_and_query("/") - /// .build() - /// .unwrap(); - /// ``` - #[inline] - pub fn new() -> Builder { - Builder::default() - } - - /// Set the `Scheme` for this URI. - /// - /// # Examples - /// - /// ``` - /// # use http::*; - /// - /// let mut builder = uri::Builder::new(); - /// builder.scheme("https"); - /// ``` - pub fn scheme<T>(self, scheme: T) -> Self - where - T: TryInto<Scheme>, - <T as TryInto<Scheme>>::Error: Into<crate::Error>, - { - self.map(move |mut parts| { - let scheme = scheme.try_into().map_err(Into::into)?; - parts.scheme = Some(scheme); - Ok(parts) - }) - } - - /// Set the `Authority` for this URI. - /// - /// # Examples - /// - /// ``` - /// # use http::*; - /// - /// let uri = uri::Builder::new() - /// .authority("tokio.rs") - /// .build() - /// .unwrap(); - /// ``` - pub fn authority<T>(self, auth: T) -> Self - where - T: TryInto<Authority>, - <T as TryInto<Authority>>::Error: Into<crate::Error>, - { - self.map(move |mut parts| { - let auth = auth.try_into().map_err(Into::into)?; - parts.authority = Some(auth); - Ok(parts) - }) - } - - /// Set the `PathAndQuery` for this URI. - /// - /// # Examples - /// - /// ``` - /// # use http::*; - /// - /// let uri = uri::Builder::new() - /// .path_and_query("/hello?foo=bar") - /// .build() - /// .unwrap(); - /// ``` - pub fn path_and_query<T>(self, p_and_q: T) -> Self - where - T: TryInto<PathAndQuery>, - <T as TryInto<PathAndQuery>>::Error: Into<crate::Error>, - { - self.map(move |mut parts| { - let p_and_q = p_and_q.try_into().map_err(Into::into)?; - parts.path_and_query = Some(p_and_q); - Ok(parts) - }) - } - - /// Consumes this builder, and tries to construct a valid `Uri` from - /// the configured pieces. - /// - /// # Errors - /// - /// This function may return an error if any previously configured argument - /// failed to parse or get converted to the internal representation. For - /// example if an invalid `scheme` was specified via `scheme("!@#%/^")` - /// the error will be returned when this function is called rather than - /// when `scheme` was called. - /// - /// Additionally, the various forms of URI require certain combinations of - /// parts to be set to be valid. If the parts don't fit into any of the - /// valid forms of URI, a new error is returned. - /// - /// # Examples - /// - /// ``` - /// # use http::*; - /// - /// let uri = Uri::builder() - /// .build() - /// .unwrap(); - /// ``` - pub fn build(self) -> Result<Uri, crate::Error> { - let parts = self.parts?; - Uri::from_parts(parts).map_err(Into::into) - } - - // private - - fn map<F>(self, func: F) -> Self - where - F: FnOnce(Parts) -> Result<Parts, crate::Error>, - { - Builder { - parts: self.parts.and_then(func), - } - } -} - -impl Default for Builder { - #[inline] - fn default() -> Builder { - Builder { - parts: Ok(Parts::default()), - } - } -} - -impl From<Uri> for Builder { - fn from(uri: Uri) -> Self { - Self { - parts: Ok(uri.into_parts()), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn build_from_str() { - let uri = Builder::new() - .scheme(Scheme::HTTP) - .authority("hyper.rs") - .path_and_query("/foo?a=1") - .build() - .unwrap(); - assert_eq!(uri.scheme_str(), Some("http")); - assert_eq!(uri.authority().unwrap().host(), "hyper.rs"); - assert_eq!(uri.path(), "/foo"); - assert_eq!(uri.query(), Some("a=1")); - } - - #[test] - fn build_from_string() { - for i in 1..10 { - let uri = Builder::new() - .path_and_query(format!("/foo?a={}", i)) - .build() - .unwrap(); - let expected_query = format!("a={}", i); - assert_eq!(uri.path(), "/foo"); - assert_eq!(uri.query(), Some(expected_query.as_str())); - } - } - - #[test] - fn build_from_string_ref() { - for i in 1..10 { - let p_a_q = format!("/foo?a={}", i); - let uri = Builder::new().path_and_query(&p_a_q).build().unwrap(); - let expected_query = format!("a={}", i); - assert_eq!(uri.path(), "/foo"); - assert_eq!(uri.query(), Some(expected_query.as_str())); - } - } - - #[test] - fn build_from_uri() { - let original_uri = Uri::default(); - let uri = Builder::from(original_uri.clone()).build().unwrap(); - assert_eq!(original_uri, uri); - } -} diff --git a/vendor/http/src/uri/mod.rs b/vendor/http/src/uri/mod.rs deleted file mode 100644 index 767f0743..00000000 --- a/vendor/http/src/uri/mod.rs +++ /dev/null @@ -1,1117 +0,0 @@ -//! URI component of request and response lines -//! -//! This module primarily contains the `Uri` type which is a component of all -//! HTTP requests and also reexports this type at the root of the crate. A URI -//! is not always a "full URL" in the sense of something you'd type into a web -//! browser, but HTTP requests may only have paths on servers but may have full -//! schemes and hostnames on clients. -//! -//! # Examples -//! -//! ``` -//! use http::Uri; -//! -//! let uri = "/foo/bar?baz".parse::<Uri>().unwrap(); -//! assert_eq!(uri.path(), "/foo/bar"); -//! assert_eq!(uri.query(), Some("baz")); -//! assert_eq!(uri.host(), None); -//! -//! let uri = "https://www.rust-lang.org/install.html".parse::<Uri>().unwrap(); -//! assert_eq!(uri.scheme_str(), Some("https")); -//! assert_eq!(uri.host(), Some("www.rust-lang.org")); -//! assert_eq!(uri.path(), "/install.html"); -//! ``` - -use crate::byte_str::ByteStr; -use std::convert::TryFrom; - -use bytes::Bytes; - -use std::error::Error; -use std::fmt; -use std::hash::{Hash, Hasher}; -use std::str::{self, FromStr}; - -use self::scheme::Scheme2; - -pub use self::authority::Authority; -pub use self::builder::Builder; -pub use self::path::PathAndQuery; -pub use self::port::Port; -pub use self::scheme::Scheme; - -mod authority; -mod builder; -mod path; -mod port; -mod scheme; -#[cfg(test)] -mod tests; - -/// The URI component of a request. -/// -/// For HTTP 1, this is included as part of the request line. From Section 5.3, -/// Request Target: -/// -/// > Once an inbound connection is obtained, the client sends an HTTP -/// > request message (Section 3) with a request-target derived from the -/// > target URI. There are four distinct formats for the request-target, -/// > depending on both the method being requested and whether the request -/// > is to a proxy. -/// > -/// > ```notrust -/// > request-target = origin-form -/// > / absolute-form -/// > / authority-form -/// > / asterisk-form -/// > ``` -/// -/// The URI is structured as follows: -/// -/// ```notrust -/// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1 -/// |-| |-------------------------------||--------| |-------------------| |-----| -/// | | | | | -/// scheme authority path query fragment -/// ``` -/// -/// For HTTP 2.0, the URI is encoded using pseudoheaders. -/// -/// # Examples -/// -/// ``` -/// use http::Uri; -/// -/// let uri = "/foo/bar?baz".parse::<Uri>().unwrap(); -/// assert_eq!(uri.path(), "/foo/bar"); -/// assert_eq!(uri.query(), Some("baz")); -/// assert_eq!(uri.host(), None); -/// -/// let uri = "https://www.rust-lang.org/install.html".parse::<Uri>().unwrap(); -/// assert_eq!(uri.scheme_str(), Some("https")); -/// assert_eq!(uri.host(), Some("www.rust-lang.org")); -/// assert_eq!(uri.path(), "/install.html"); -/// ``` -#[derive(Clone)] -pub struct Uri { - scheme: Scheme, - authority: Authority, - path_and_query: PathAndQuery, -} - -/// The various parts of a URI. -/// -/// This struct is used to provide to and retrieve from a URI. -#[derive(Debug, Default)] -pub struct Parts { - /// The scheme component of a URI - pub scheme: Option<Scheme>, - - /// The authority component of a URI - pub authority: Option<Authority>, - - /// The origin-form component of a URI - pub path_and_query: Option<PathAndQuery>, - - /// Allow extending in the future - _priv: (), -} - -/// An error resulting from a failed attempt to construct a URI. -#[derive(Debug)] -pub struct InvalidUri(ErrorKind); - -/// An error resulting from a failed attempt to construct a URI. -#[derive(Debug)] -pub struct InvalidUriParts(InvalidUri); - -#[derive(Debug, Eq, PartialEq)] -enum ErrorKind { - InvalidUriChar, - InvalidScheme, - InvalidAuthority, - InvalidPort, - InvalidFormat, - SchemeMissing, - AuthorityMissing, - PathAndQueryMissing, - TooLong, - Empty, - SchemeTooLong, -} - -// u16::MAX is reserved for None -const MAX_LEN: usize = (u16::MAX - 1) as usize; - -// URI_CHARS is a table of valid characters in a URI. An entry in the table is -// 0 for invalid characters. For valid characters the entry is itself (i.e. -// the entry for 33 is b'!' because b'!' == 33u8). An important characteristic -// of this table is that all entries above 127 are invalid. This makes all of the -// valid entries a valid single-byte UTF-8 code point. This means that a slice -// of such valid entries is valid UTF-8. -#[rustfmt::skip] -const URI_CHARS: [u8; 256] = [ - // 0 1 2 3 4 5 6 7 8 9 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x - 0, 0, 0, b'!', 0, b'#', b'$', 0, b'&', b'\'', // 3x - b'(', b')', b'*', b'+', b',', b'-', b'.', b'/', b'0', b'1', // 4x - b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b':', b';', // 5x - 0, b'=', 0, b'?', b'@', b'A', b'B', b'C', b'D', b'E', // 6x - b'F', b'G', b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', // 7x - b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W', b'X', b'Y', // 8x - b'Z', b'[', 0, b']', 0, b'_', 0, b'a', b'b', b'c', // 9x - b'd', b'e', b'f', b'g', b'h', b'i', b'j', b'k', b'l', b'm', // 10x - b'n', b'o', b'p', b'q', b'r', b's', b't', b'u', b'v', b'w', // 11x - b'x', b'y', b'z', 0, 0, 0, b'~', 0, 0, 0, // 12x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 13x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 14x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 15x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 17x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 18x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 19x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 21x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 22x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 23x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 24x - 0, 0, 0, 0, 0, 0 // 25x -]; - -impl Uri { - /// Creates a new builder-style object to manufacture a `Uri`. - /// - /// This method returns an instance of `Builder` which can be usd to - /// create a `Uri`. - /// - /// # Examples - /// - /// ``` - /// use http::Uri; - /// - /// let uri = Uri::builder() - /// .scheme("https") - /// .authority("hyper.rs") - /// .path_and_query("/") - /// .build() - /// .unwrap(); - /// ``` - pub fn builder() -> Builder { - Builder::new() - } - - /// Attempt to convert a `Parts` into a `Uri`. - /// - /// # Examples - /// - /// Relative URI - /// - /// ``` - /// # use http::uri::*; - /// let mut parts = Parts::default(); - /// parts.path_and_query = Some("/foo".parse().unwrap()); - /// - /// let uri = Uri::from_parts(parts).unwrap(); - /// - /// assert_eq!(uri.path(), "/foo"); - /// - /// assert!(uri.scheme().is_none()); - /// assert!(uri.authority().is_none()); - /// ``` - /// - /// Absolute URI - /// - /// ``` - /// # use http::uri::*; - /// let mut parts = Parts::default(); - /// parts.scheme = Some("http".parse().unwrap()); - /// parts.authority = Some("foo.com".parse().unwrap()); - /// parts.path_and_query = Some("/foo".parse().unwrap()); - /// - /// let uri = Uri::from_parts(parts).unwrap(); - /// - /// assert_eq!(uri.scheme().unwrap().as_str(), "http"); - /// assert_eq!(uri.authority().unwrap(), "foo.com"); - /// assert_eq!(uri.path(), "/foo"); - /// ``` - pub fn from_parts(src: Parts) -> Result<Uri, InvalidUriParts> { - if src.scheme.is_some() { - if src.authority.is_none() { - return Err(ErrorKind::AuthorityMissing.into()); - } - - if src.path_and_query.is_none() { - return Err(ErrorKind::PathAndQueryMissing.into()); - } - } else if src.authority.is_some() && src.path_and_query.is_some() { - return Err(ErrorKind::SchemeMissing.into()); - } - - let scheme = match src.scheme { - Some(scheme) => scheme, - None => Scheme { - inner: Scheme2::None, - }, - }; - - let authority = match src.authority { - Some(authority) => authority, - None => Authority::empty(), - }; - - let path_and_query = match src.path_and_query { - Some(path_and_query) => path_and_query, - None => PathAndQuery::empty(), - }; - - Ok(Uri { - scheme, - authority, - path_and_query, - }) - } - - /// Attempt to convert a `Bytes` buffer to a `Uri`. - /// - /// This will try to prevent a copy if the type passed is the type used - /// internally, and will copy the data if it is not. - pub fn from_maybe_shared<T>(src: T) -> Result<Self, InvalidUri> - where - T: AsRef<[u8]> + 'static, - { - if_downcast_into!(T, Bytes, src, { - return Uri::from_shared(src); - }); - - Uri::try_from(src.as_ref()) - } - - // Not public while `bytes` is unstable. - fn from_shared(s: Bytes) -> Result<Uri, InvalidUri> { - use self::ErrorKind::*; - - if s.len() > MAX_LEN { - return Err(TooLong.into()); - } - - match s.len() { - 0 => { - return Err(Empty.into()); - } - 1 => match s[0] { - b'/' => { - return Ok(Uri { - scheme: Scheme::empty(), - authority: Authority::empty(), - path_and_query: PathAndQuery::slash(), - }); - } - b'*' => { - return Ok(Uri { - scheme: Scheme::empty(), - authority: Authority::empty(), - path_and_query: PathAndQuery::star(), - }); - } - _ => { - let authority = Authority::from_shared(s)?; - - return Ok(Uri { - scheme: Scheme::empty(), - authority, - path_and_query: PathAndQuery::empty(), - }); - } - }, - _ => {} - } - - if s[0] == b'/' { - return Ok(Uri { - scheme: Scheme::empty(), - authority: Authority::empty(), - path_and_query: PathAndQuery::from_shared(s)?, - }); - } - - parse_full(s) - } - - /// Convert a `Uri` from a static string. - /// - /// This function will not perform any copying, however the string is - /// checked to ensure that it is valid. - /// - /// # Panics - /// - /// This function panics if the argument is an invalid URI. - /// - /// # Examples - /// - /// ``` - /// # use http::uri::Uri; - /// let uri = Uri::from_static("http://example.com/foo"); - /// - /// assert_eq!(uri.host().unwrap(), "example.com"); - /// assert_eq!(uri.path(), "/foo"); - /// ``` - pub fn from_static(src: &'static str) -> Self { - let s = Bytes::from_static(src.as_bytes()); - match Uri::from_shared(s) { - Ok(uri) => uri, - Err(e) => panic!("static str is not valid URI: {}", e), - } - } - - /// Convert a `Uri` into `Parts`. - /// - /// # Note - /// - /// This is just an inherent method providing the same functionality as - /// `let parts: Parts = uri.into()` - /// - /// # Examples - /// - /// ``` - /// # use http::uri::*; - /// let uri: Uri = "/foo".parse().unwrap(); - /// - /// let parts = uri.into_parts(); - /// - /// assert_eq!(parts.path_and_query.unwrap(), "/foo"); - /// - /// assert!(parts.scheme.is_none()); - /// assert!(parts.authority.is_none()); - /// ``` - #[inline] - pub fn into_parts(self) -> Parts { - self.into() - } - - /// Returns the path & query components of the Uri - #[inline] - pub fn path_and_query(&self) -> Option<&PathAndQuery> { - if !self.scheme.inner.is_none() || self.authority.data.is_empty() { - Some(&self.path_and_query) - } else { - None - } - } - - /// Get the path of this `Uri`. - /// - /// Both relative and absolute URIs contain a path component, though it - /// might be the empty string. The path component is **case sensitive**. - /// - /// ```notrust - /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1 - /// |--------| - /// | - /// path - /// ``` - /// - /// If the URI is `*` then the path component is equal to `*`. - /// - /// # Examples - /// - /// A relative URI - /// - /// ``` - /// # use http::Uri; - /// - /// let uri: Uri = "/hello/world".parse().unwrap(); - /// - /// assert_eq!(uri.path(), "/hello/world"); - /// ``` - /// - /// An absolute URI - /// - /// ``` - /// # use http::Uri; - /// let uri: Uri = "http://example.org/hello/world".parse().unwrap(); - /// - /// assert_eq!(uri.path(), "/hello/world"); - /// ``` - #[inline] - pub fn path(&self) -> &str { - if self.has_path() { - self.path_and_query.path() - } else { - "" - } - } - - /// Get the scheme of this `Uri`. - /// - /// The URI scheme refers to a specification for assigning identifiers - /// within that scheme. Only absolute URIs contain a scheme component, but - /// not all absolute URIs will contain a scheme component. Although scheme - /// names are case-insensitive, the canonical form is lowercase. - /// - /// ```notrust - /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1 - /// |-| - /// | - /// scheme - /// ``` - /// - /// # Examples - /// - /// Absolute URI - /// - /// ``` - /// use http::uri::{Scheme, Uri}; - /// - /// let uri: Uri = "http://example.org/hello/world".parse().unwrap(); - /// - /// assert_eq!(uri.scheme(), Some(&Scheme::HTTP)); - /// ``` - /// - /// - /// Relative URI - /// - /// ``` - /// # use http::Uri; - /// let uri: Uri = "/hello/world".parse().unwrap(); - /// - /// assert!(uri.scheme().is_none()); - /// ``` - #[inline] - pub fn scheme(&self) -> Option<&Scheme> { - if self.scheme.inner.is_none() { - None - } else { - Some(&self.scheme) - } - } - - /// Get the scheme of this `Uri` as a `&str`. - /// - /// # Example - /// - /// ``` - /// # use http::Uri; - /// let uri: Uri = "http://example.org/hello/world".parse().unwrap(); - /// - /// assert_eq!(uri.scheme_str(), Some("http")); - /// ``` - #[inline] - pub fn scheme_str(&self) -> Option<&str> { - if self.scheme.inner.is_none() { - None - } else { - Some(self.scheme.as_str()) - } - } - - /// Get the authority of this `Uri`. - /// - /// The authority is a hierarchical element for naming authority such that - /// the remainder of the URI is delegated to that authority. For HTTP, the - /// authority consists of the host and port. The host portion of the - /// authority is **case-insensitive**. - /// - /// The authority also includes a `username:password` component, however - /// the use of this is deprecated and should be avoided. - /// - /// ```notrust - /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1 - /// |-------------------------------| - /// | - /// authority - /// ``` - /// - /// # Examples - /// - /// Absolute URI - /// - /// ``` - /// # use http::Uri; - /// let uri: Uri = "http://example.org:80/hello/world".parse().unwrap(); - /// - /// assert_eq!(uri.authority().map(|a| a.as_str()), Some("example.org:80")); - /// ``` - /// - /// - /// Relative URI - /// - /// ``` - /// # use http::Uri; - /// let uri: Uri = "/hello/world".parse().unwrap(); - /// - /// assert!(uri.authority().is_none()); - /// ``` - #[inline] - pub fn authority(&self) -> Option<&Authority> { - if self.authority.data.is_empty() { - None - } else { - Some(&self.authority) - } - } - - /// Get the host of this `Uri`. - /// - /// The host subcomponent of authority is identified by an IP literal - /// encapsulated within square brackets, an IPv4 address in dotted- decimal - /// form, or a registered name. The host subcomponent is **case-insensitive**. - /// - /// ```notrust - /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1 - /// |---------| - /// | - /// host - /// ``` - /// - /// # Examples - /// - /// Absolute URI - /// - /// ``` - /// # use http::Uri; - /// let uri: Uri = "http://example.org:80/hello/world".parse().unwrap(); - /// - /// assert_eq!(uri.host(), Some("example.org")); - /// ``` - /// - /// - /// Relative URI - /// - /// ``` - /// # use http::Uri; - /// let uri: Uri = "/hello/world".parse().unwrap(); - /// - /// assert!(uri.host().is_none()); - /// ``` - #[inline] - pub fn host(&self) -> Option<&str> { - self.authority().map(|a| a.host()) - } - - /// Get the port part of this `Uri`. - /// - /// The port subcomponent of authority is designated by an optional port - /// number following the host and delimited from it by a single colon (":") - /// character. It can be turned into a decimal port number with the `as_u16` - /// method or as a `str` with the `as_str` method. - /// - /// ```notrust - /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1 - /// |-| - /// | - /// port - /// ``` - /// - /// # Examples - /// - /// Absolute URI with port - /// - /// ``` - /// # use http::Uri; - /// let uri: Uri = "http://example.org:80/hello/world".parse().unwrap(); - /// - /// let port = uri.port().unwrap(); - /// assert_eq!(port.as_u16(), 80); - /// ``` - /// - /// Absolute URI without port - /// - /// ``` - /// # use http::Uri; - /// let uri: Uri = "http://example.org/hello/world".parse().unwrap(); - /// - /// assert!(uri.port().is_none()); - /// ``` - /// - /// Relative URI - /// - /// ``` - /// # use http::Uri; - /// let uri: Uri = "/hello/world".parse().unwrap(); - /// - /// assert!(uri.port().is_none()); - /// ``` - pub fn port(&self) -> Option<Port<&str>> { - self.authority().and_then(|a| a.port()) - } - - /// Get the port of this `Uri` as a `u16`. - /// - /// - /// # Example - /// - /// ``` - /// # use http::{Uri, uri::Port}; - /// let uri: Uri = "http://example.org:80/hello/world".parse().unwrap(); - /// - /// assert_eq!(uri.port_u16(), Some(80)); - /// ``` - pub fn port_u16(&self) -> Option<u16> { - self.port().map(|p| p.as_u16()) - } - - /// Get the query string of this `Uri`, starting after the `?`. - /// - /// The query component contains non-hierarchical data that, along with data - /// in the path component, serves to identify a resource within the scope of - /// the URI's scheme and naming authority (if any). The query component is - /// indicated by the first question mark ("?") character and terminated by a - /// number sign ("#") character or by the end of the URI. - /// - /// ```notrust - /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1 - /// |-------------------| - /// | - /// query - /// ``` - /// - /// # Examples - /// - /// Absolute URI - /// - /// ``` - /// # use http::Uri; - /// let uri: Uri = "http://example.org/hello/world?key=value".parse().unwrap(); - /// - /// assert_eq!(uri.query(), Some("key=value")); - /// ``` - /// - /// Relative URI with a query string component - /// - /// ``` - /// # use http::Uri; - /// let uri: Uri = "/hello/world?key=value&foo=bar".parse().unwrap(); - /// - /// assert_eq!(uri.query(), Some("key=value&foo=bar")); - /// ``` - /// - /// Relative URI without a query string component - /// - /// ``` - /// # use http::Uri; - /// let uri: Uri = "/hello/world".parse().unwrap(); - /// - /// assert!(uri.query().is_none()); - /// ``` - #[inline] - pub fn query(&self) -> Option<&str> { - self.path_and_query.query() - } - - fn has_path(&self) -> bool { - !self.path_and_query.data.is_empty() || !self.scheme.inner.is_none() - } -} - -impl<'a> TryFrom<&'a [u8]> for Uri { - type Error = InvalidUri; - - #[inline] - fn try_from(t: &'a [u8]) -> Result<Self, Self::Error> { - Uri::from_shared(Bytes::copy_from_slice(t)) - } -} - -impl<'a> TryFrom<&'a str> for Uri { - type Error = InvalidUri; - - #[inline] - fn try_from(t: &'a str) -> Result<Self, Self::Error> { - t.parse() - } -} - -impl<'a> TryFrom<&'a String> for Uri { - type Error = InvalidUri; - - #[inline] - fn try_from(t: &'a String) -> Result<Self, Self::Error> { - t.parse() - } -} - -impl TryFrom<String> for Uri { - type Error = InvalidUri; - - #[inline] - fn try_from(t: String) -> Result<Self, Self::Error> { - Uri::from_shared(Bytes::from(t)) - } -} - -impl TryFrom<Vec<u8>> for Uri { - type Error = InvalidUri; - - #[inline] - fn try_from(vec: Vec<u8>) -> Result<Self, Self::Error> { - Uri::from_shared(Bytes::from(vec)) - } -} - -impl TryFrom<Parts> for Uri { - type Error = InvalidUriParts; - - #[inline] - fn try_from(src: Parts) -> Result<Self, Self::Error> { - Uri::from_parts(src) - } -} - -impl<'a> TryFrom<&'a Uri> for Uri { - type Error = crate::Error; - - #[inline] - fn try_from(src: &'a Uri) -> Result<Self, Self::Error> { - Ok(src.clone()) - } -} - -/// Convert an `Authority` into a `Uri`. -impl From<Authority> for Uri { - fn from(authority: Authority) -> Self { - Self { - scheme: Scheme::empty(), - authority, - path_and_query: PathAndQuery::empty(), - } - } -} - -/// Convert a `PathAndQuery` into a `Uri`. -impl From<PathAndQuery> for Uri { - fn from(path_and_query: PathAndQuery) -> Self { - Self { - scheme: Scheme::empty(), - authority: Authority::empty(), - path_and_query, - } - } -} - -/// Convert a `Uri` into `Parts` -impl From<Uri> for Parts { - fn from(src: Uri) -> Self { - let path_and_query = if src.has_path() { - Some(src.path_and_query) - } else { - None - }; - - let scheme = match src.scheme.inner { - Scheme2::None => None, - _ => Some(src.scheme), - }; - - let authority = if src.authority.data.is_empty() { - None - } else { - Some(src.authority) - }; - - Parts { - scheme, - authority, - path_and_query, - _priv: (), - } - } -} - -fn parse_full(mut s: Bytes) -> Result<Uri, InvalidUri> { - // Parse the scheme - let scheme = match Scheme2::parse(&s[..])? { - Scheme2::None => Scheme2::None, - Scheme2::Standard(p) => { - // TODO: use truncate - let _ = s.split_to(p.len() + 3); - Scheme2::Standard(p) - } - Scheme2::Other(n) => { - // Grab the protocol - let mut scheme = s.split_to(n + 3); - - // Strip ://, TODO: truncate - let _ = scheme.split_off(n); - - // Allocate the ByteStr - let val = unsafe { ByteStr::from_utf8_unchecked(scheme) }; - - Scheme2::Other(Box::new(val)) - } - }; - - // Find the end of the authority. The scheme will already have been - // extracted. - let authority_end = Authority::parse(&s[..])?; - - if scheme.is_none() { - if authority_end != s.len() { - return Err(ErrorKind::InvalidFormat.into()); - } - - let authority = Authority { - data: unsafe { ByteStr::from_utf8_unchecked(s) }, - }; - - return Ok(Uri { - scheme: scheme.into(), - authority, - path_and_query: PathAndQuery::empty(), - }); - } - - // Authority is required when absolute - if authority_end == 0 { - return Err(ErrorKind::InvalidFormat.into()); - } - - let authority = s.split_to(authority_end); - let authority = Authority { - data: unsafe { ByteStr::from_utf8_unchecked(authority) }, - }; - - Ok(Uri { - scheme: scheme.into(), - authority, - path_and_query: PathAndQuery::from_shared(s)?, - }) -} - -impl FromStr for Uri { - type Err = InvalidUri; - - #[inline] - fn from_str(s: &str) -> Result<Uri, InvalidUri> { - Uri::try_from(s.as_bytes()) - } -} - -impl PartialEq for Uri { - fn eq(&self, other: &Uri) -> bool { - if self.scheme() != other.scheme() { - return false; - } - - if self.authority() != other.authority() { - return false; - } - - if self.path() != other.path() { - return false; - } - - if self.query() != other.query() { - return false; - } - - true - } -} - -impl PartialEq<str> for Uri { - fn eq(&self, other: &str) -> bool { - let mut other = other.as_bytes(); - let mut absolute = false; - - if let Some(scheme) = self.scheme() { - let scheme = scheme.as_str().as_bytes(); - absolute = true; - - if other.len() < scheme.len() + 3 { - return false; - } - - if !scheme.eq_ignore_ascii_case(&other[..scheme.len()]) { - return false; - } - - other = &other[scheme.len()..]; - - if &other[..3] != b"://" { - return false; - } - - other = &other[3..]; - } - - if let Some(auth) = self.authority() { - let len = auth.data.len(); - absolute = true; - - if other.len() < len { - return false; - } - - if !auth.data.as_bytes().eq_ignore_ascii_case(&other[..len]) { - return false; - } - - other = &other[len..]; - } - - let path = self.path(); - - if other.len() < path.len() || path.as_bytes() != &other[..path.len()] { - if absolute && path == "/" { - // PathAndQuery can be omitted, fall through - } else { - return false; - } - } else { - other = &other[path.len()..]; - } - - if let Some(query) = self.query() { - if other.is_empty() { - return query.is_empty(); - } - - if other[0] != b'?' { - return false; - } - - other = &other[1..]; - - if other.len() < query.len() { - return false; - } - - if query.as_bytes() != &other[..query.len()] { - return false; - } - - other = &other[query.len()..]; - } - - other.is_empty() || other[0] == b'#' - } -} - -impl PartialEq<Uri> for str { - fn eq(&self, uri: &Uri) -> bool { - uri == self - } -} - -impl<'a> PartialEq<&'a str> for Uri { - fn eq(&self, other: &&'a str) -> bool { - self == *other - } -} - -impl<'a> PartialEq<Uri> for &'a str { - fn eq(&self, uri: &Uri) -> bool { - uri == *self - } -} - -impl Eq for Uri {} - -/// Returns a `Uri` representing `/` -impl Default for Uri { - #[inline] - fn default() -> Uri { - Uri { - scheme: Scheme::empty(), - authority: Authority::empty(), - path_and_query: PathAndQuery::slash(), - } - } -} - -impl fmt::Display for Uri { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let Some(scheme) = self.scheme() { - write!(f, "{}://", scheme)?; - } - - if let Some(authority) = self.authority() { - write!(f, "{}", authority)?; - } - - write!(f, "{}", self.path())?; - - if let Some(query) = self.query() { - write!(f, "?{}", query)?; - } - - Ok(()) - } -} - -impl fmt::Debug for Uri { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self, f) - } -} - -impl From<ErrorKind> for InvalidUri { - fn from(src: ErrorKind) -> InvalidUri { - InvalidUri(src) - } -} - -impl From<ErrorKind> for InvalidUriParts { - fn from(src: ErrorKind) -> InvalidUriParts { - InvalidUriParts(src.into()) - } -} - -impl InvalidUri { - fn s(&self) -> &str { - match self.0 { - ErrorKind::InvalidUriChar => "invalid uri character", - ErrorKind::InvalidScheme => "invalid scheme", - ErrorKind::InvalidAuthority => "invalid authority", - ErrorKind::InvalidPort => "invalid port", - ErrorKind::InvalidFormat => "invalid format", - ErrorKind::SchemeMissing => "scheme missing", - ErrorKind::AuthorityMissing => "authority missing", - ErrorKind::PathAndQueryMissing => "path missing", - ErrorKind::TooLong => "uri too long", - ErrorKind::Empty => "empty string", - ErrorKind::SchemeTooLong => "scheme too long", - } - } -} - -impl fmt::Display for InvalidUri { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.s().fmt(f) - } -} - -impl Error for InvalidUri {} - -impl fmt::Display for InvalidUriParts { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) - } -} - -impl Error for InvalidUriParts {} - -impl Hash for Uri { - fn hash<H>(&self, state: &mut H) - where - H: Hasher, - { - if !self.scheme.inner.is_none() { - self.scheme.hash(state); - state.write_u8(0xff); - } - - if let Some(auth) = self.authority() { - auth.hash(state); - } - - Hash::hash_slice(self.path().as_bytes(), state); - - if let Some(query) = self.query() { - b'?'.hash(state); - Hash::hash_slice(query.as_bytes(), state); - } - } -} diff --git a/vendor/http/src/uri/path.rs b/vendor/http/src/uri/path.rs deleted file mode 100644 index 42db1f92..00000000 --- a/vendor/http/src/uri/path.rs +++ /dev/null @@ -1,604 +0,0 @@ -use std::convert::TryFrom; -use std::str::FromStr; -use std::{cmp, fmt, hash, str}; - -use bytes::Bytes; - -use super::{ErrorKind, InvalidUri}; -use crate::byte_str::ByteStr; - -/// Represents the path component of a URI -#[derive(Clone)] -pub struct PathAndQuery { - pub(super) data: ByteStr, - pub(super) query: u16, -} - -const NONE: u16 = u16::MAX; - -impl PathAndQuery { - // Not public while `bytes` is unstable. - pub(super) fn from_shared(mut src: Bytes) -> Result<Self, InvalidUri> { - let mut query = NONE; - let mut fragment = None; - - let mut is_maybe_not_utf8 = false; - - // block for iterator borrow - { - let mut iter = src.as_ref().iter().enumerate(); - - // path ... - for (i, &b) in &mut iter { - // See https://url.spec.whatwg.org/#path-state - match b { - b'?' => { - debug_assert_eq!(query, NONE); - query = i as u16; - break; - } - b'#' => { - fragment = Some(i); - break; - } - - // This is the range of bytes that don't need to be - // percent-encoded in the path. If it should have been - // percent-encoded, then error. - #[rustfmt::skip] - 0x21 | - 0x24..=0x3B | - 0x3D | - 0x40..=0x5F | - 0x61..=0x7A | - 0x7C | - 0x7E => {} - - // potentially utf8, might not, should check - 0x7F..=0xFF => { - is_maybe_not_utf8 = true; - } - - // These are code points that are supposed to be - // percent-encoded in the path but there are clients - // out there sending them as is and httparse accepts - // to parse those requests, so they are allowed here - // for parity. - // - // For reference, those are code points that are used - // to send requests with JSON directly embedded in - // the URI path. Yes, those things happen for real. - #[rustfmt::skip] - b'"' | - b'{' | b'}' => {} - - _ => return Err(ErrorKind::InvalidUriChar.into()), - } - } - - // query ... - if query != NONE { - for (i, &b) in iter { - match b { - // While queries *should* be percent-encoded, most - // bytes are actually allowed... - // See https://url.spec.whatwg.org/#query-state - // - // Allowed: 0x21 / 0x24 - 0x3B / 0x3D / 0x3F - 0x7E - #[rustfmt::skip] - 0x21 | - 0x24..=0x3B | - 0x3D | - 0x3F..=0x7E => {} - - 0x7F..=0xFF => { - is_maybe_not_utf8 = true; - } - - b'#' => { - fragment = Some(i); - break; - } - - _ => return Err(ErrorKind::InvalidUriChar.into()), - } - } - } - } - - if let Some(i) = fragment { - src.truncate(i); - } - - let data = if is_maybe_not_utf8 { - ByteStr::from_utf8(src).map_err(|_| ErrorKind::InvalidUriChar)? - } else { - unsafe { ByteStr::from_utf8_unchecked(src) } - }; - - Ok(PathAndQuery { data, query }) - } - - /// Convert a `PathAndQuery` from a static string. - /// - /// This function will not perform any copying, however the string is - /// checked to ensure that it is valid. - /// - /// # Panics - /// - /// This function panics if the argument is an invalid path and query. - /// - /// # Examples - /// - /// ``` - /// # use http::uri::*; - /// let v = PathAndQuery::from_static("/hello?world"); - /// - /// assert_eq!(v.path(), "/hello"); - /// assert_eq!(v.query(), Some("world")); - /// ``` - #[inline] - pub fn from_static(src: &'static str) -> Self { - let src = Bytes::from_static(src.as_bytes()); - - PathAndQuery::from_shared(src).unwrap() - } - - /// Attempt to convert a `Bytes` buffer to a `PathAndQuery`. - /// - /// This will try to prevent a copy if the type passed is the type used - /// internally, and will copy the data if it is not. - pub fn from_maybe_shared<T>(src: T) -> Result<Self, InvalidUri> - where - T: AsRef<[u8]> + 'static, - { - if_downcast_into!(T, Bytes, src, { - return PathAndQuery::from_shared(src); - }); - - PathAndQuery::try_from(src.as_ref()) - } - - pub(super) fn empty() -> Self { - PathAndQuery { - data: ByteStr::new(), - query: NONE, - } - } - - pub(super) fn slash() -> Self { - PathAndQuery { - data: ByteStr::from_static("/"), - query: NONE, - } - } - - pub(super) fn star() -> Self { - PathAndQuery { - data: ByteStr::from_static("*"), - query: NONE, - } - } - - /// Returns the path component - /// - /// The path component is **case sensitive**. - /// - /// ```notrust - /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1 - /// |--------| - /// | - /// path - /// ``` - /// - /// If the URI is `*` then the path component is equal to `*`. - /// - /// # Examples - /// - /// ``` - /// # use http::uri::*; - /// - /// let path_and_query: PathAndQuery = "/hello/world".parse().unwrap(); - /// - /// assert_eq!(path_and_query.path(), "/hello/world"); - /// ``` - #[inline] - pub fn path(&self) -> &str { - let ret = if self.query == NONE { - &self.data[..] - } else { - &self.data[..self.query as usize] - }; - - if ret.is_empty() { - return "/"; - } - - ret - } - - /// Returns the query string component - /// - /// The query component contains non-hierarchical data that, along with data - /// in the path component, serves to identify a resource within the scope of - /// the URI's scheme and naming authority (if any). The query component is - /// indicated by the first question mark ("?") character and terminated by a - /// number sign ("#") character or by the end of the URI. - /// - /// ```notrust - /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1 - /// |-------------------| - /// | - /// query - /// ``` - /// - /// # Examples - /// - /// With a query string component - /// - /// ``` - /// # use http::uri::*; - /// let path_and_query: PathAndQuery = "/hello/world?key=value&foo=bar".parse().unwrap(); - /// - /// assert_eq!(path_and_query.query(), Some("key=value&foo=bar")); - /// ``` - /// - /// Without a query string component - /// - /// ``` - /// # use http::uri::*; - /// let path_and_query: PathAndQuery = "/hello/world".parse().unwrap(); - /// - /// assert!(path_and_query.query().is_none()); - /// ``` - #[inline] - pub fn query(&self) -> Option<&str> { - if self.query == NONE { - None - } else { - let i = self.query + 1; - Some(&self.data[i as usize..]) - } - } - - /// Returns the path and query as a string component. - /// - /// # Examples - /// - /// With a query string component - /// - /// ``` - /// # use http::uri::*; - /// let path_and_query: PathAndQuery = "/hello/world?key=value&foo=bar".parse().unwrap(); - /// - /// assert_eq!(path_and_query.as_str(), "/hello/world?key=value&foo=bar"); - /// ``` - /// - /// Without a query string component - /// - /// ``` - /// # use http::uri::*; - /// let path_and_query: PathAndQuery = "/hello/world".parse().unwrap(); - /// - /// assert_eq!(path_and_query.as_str(), "/hello/world"); - /// ``` - #[inline] - pub fn as_str(&self) -> &str { - let ret = &self.data[..]; - if ret.is_empty() { - return "/"; - } - ret - } -} - -impl<'a> TryFrom<&'a [u8]> for PathAndQuery { - type Error = InvalidUri; - #[inline] - fn try_from(s: &'a [u8]) -> Result<Self, Self::Error> { - PathAndQuery::from_shared(Bytes::copy_from_slice(s)) - } -} - -impl<'a> TryFrom<&'a str> for PathAndQuery { - type Error = InvalidUri; - #[inline] - fn try_from(s: &'a str) -> Result<Self, Self::Error> { - TryFrom::try_from(s.as_bytes()) - } -} - -impl TryFrom<Vec<u8>> for PathAndQuery { - type Error = InvalidUri; - #[inline] - fn try_from(vec: Vec<u8>) -> Result<Self, Self::Error> { - PathAndQuery::from_shared(vec.into()) - } -} - -impl TryFrom<String> for PathAndQuery { - type Error = InvalidUri; - #[inline] - fn try_from(s: String) -> Result<Self, Self::Error> { - PathAndQuery::from_shared(s.into()) - } -} - -impl TryFrom<&String> for PathAndQuery { - type Error = InvalidUri; - #[inline] - fn try_from(s: &String) -> Result<Self, Self::Error> { - TryFrom::try_from(s.as_bytes()) - } -} - -impl FromStr for PathAndQuery { - type Err = InvalidUri; - #[inline] - fn from_str(s: &str) -> Result<Self, InvalidUri> { - TryFrom::try_from(s) - } -} - -impl fmt::Debug for PathAndQuery { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self, f) - } -} - -impl fmt::Display for PathAndQuery { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - if !self.data.is_empty() { - match self.data.as_bytes()[0] { - b'/' | b'*' => write!(fmt, "{}", &self.data[..]), - _ => write!(fmt, "/{}", &self.data[..]), - } - } else { - write!(fmt, "/") - } - } -} - -impl hash::Hash for PathAndQuery { - fn hash<H: hash::Hasher>(&self, state: &mut H) { - self.data.hash(state); - } -} - -// ===== PartialEq / PartialOrd ===== - -impl PartialEq for PathAndQuery { - #[inline] - fn eq(&self, other: &PathAndQuery) -> bool { - self.data == other.data - } -} - -impl Eq for PathAndQuery {} - -impl PartialEq<str> for PathAndQuery { - #[inline] - fn eq(&self, other: &str) -> bool { - self.as_str() == other - } -} - -impl<'a> PartialEq<PathAndQuery> for &'a str { - #[inline] - fn eq(&self, other: &PathAndQuery) -> bool { - self == &other.as_str() - } -} - -impl<'a> PartialEq<&'a str> for PathAndQuery { - #[inline] - fn eq(&self, other: &&'a str) -> bool { - self.as_str() == *other - } -} - -impl PartialEq<PathAndQuery> for str { - #[inline] - fn eq(&self, other: &PathAndQuery) -> bool { - self == other.as_str() - } -} - -impl PartialEq<String> for PathAndQuery { - #[inline] - fn eq(&self, other: &String) -> bool { - self.as_str() == other.as_str() - } -} - -impl PartialEq<PathAndQuery> for String { - #[inline] - fn eq(&self, other: &PathAndQuery) -> bool { - self.as_str() == other.as_str() - } -} - -impl PartialOrd for PathAndQuery { - #[inline] - fn partial_cmp(&self, other: &PathAndQuery) -> Option<cmp::Ordering> { - self.as_str().partial_cmp(other.as_str()) - } -} - -impl PartialOrd<str> for PathAndQuery { - #[inline] - fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> { - self.as_str().partial_cmp(other) - } -} - -impl PartialOrd<PathAndQuery> for str { - #[inline] - fn partial_cmp(&self, other: &PathAndQuery) -> Option<cmp::Ordering> { - self.partial_cmp(other.as_str()) - } -} - -impl<'a> PartialOrd<&'a str> for PathAndQuery { - #[inline] - fn partial_cmp(&self, other: &&'a str) -> Option<cmp::Ordering> { - self.as_str().partial_cmp(*other) - } -} - -impl<'a> PartialOrd<PathAndQuery> for &'a str { - #[inline] - fn partial_cmp(&self, other: &PathAndQuery) -> Option<cmp::Ordering> { - self.partial_cmp(&other.as_str()) - } -} - -impl PartialOrd<String> for PathAndQuery { - #[inline] - fn partial_cmp(&self, other: &String) -> Option<cmp::Ordering> { - self.as_str().partial_cmp(other.as_str()) - } -} - -impl PartialOrd<PathAndQuery> for String { - #[inline] - fn partial_cmp(&self, other: &PathAndQuery) -> Option<cmp::Ordering> { - self.as_str().partial_cmp(other.as_str()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn equal_to_self_of_same_path() { - let p1: PathAndQuery = "/hello/world&foo=bar".parse().unwrap(); - let p2: PathAndQuery = "/hello/world&foo=bar".parse().unwrap(); - assert_eq!(p1, p2); - assert_eq!(p2, p1); - } - - #[test] - fn not_equal_to_self_of_different_path() { - let p1: PathAndQuery = "/hello/world&foo=bar".parse().unwrap(); - let p2: PathAndQuery = "/world&foo=bar".parse().unwrap(); - assert_ne!(p1, p2); - assert_ne!(p2, p1); - } - - #[test] - fn equates_with_a_str() { - let path_and_query: PathAndQuery = "/hello/world&foo=bar".parse().unwrap(); - assert_eq!(&path_and_query, "/hello/world&foo=bar"); - assert_eq!("/hello/world&foo=bar", &path_and_query); - assert_eq!(path_and_query, "/hello/world&foo=bar"); - assert_eq!("/hello/world&foo=bar", path_and_query); - } - - #[test] - fn not_equal_with_a_str_of_a_different_path() { - let path_and_query: PathAndQuery = "/hello/world&foo=bar".parse().unwrap(); - // as a reference - assert_ne!(&path_and_query, "/hello&foo=bar"); - assert_ne!("/hello&foo=bar", &path_and_query); - // without reference - assert_ne!(path_and_query, "/hello&foo=bar"); - assert_ne!("/hello&foo=bar", path_and_query); - } - - #[test] - fn equates_with_a_string() { - let path_and_query: PathAndQuery = "/hello/world&foo=bar".parse().unwrap(); - assert_eq!(path_and_query, "/hello/world&foo=bar".to_string()); - assert_eq!("/hello/world&foo=bar".to_string(), path_and_query); - } - - #[test] - fn not_equal_with_a_string_of_a_different_path() { - let path_and_query: PathAndQuery = "/hello/world&foo=bar".parse().unwrap(); - assert_ne!(path_and_query, "/hello&foo=bar".to_string()); - assert_ne!("/hello&foo=bar".to_string(), path_and_query); - } - - #[test] - fn compares_to_self() { - let p1: PathAndQuery = "/a/world&foo=bar".parse().unwrap(); - let p2: PathAndQuery = "/b/world&foo=bar".parse().unwrap(); - assert!(p1 < p2); - assert!(p2 > p1); - } - - #[test] - fn compares_with_a_str() { - let path_and_query: PathAndQuery = "/b/world&foo=bar".parse().unwrap(); - // by ref - assert!(&path_and_query < "/c/world&foo=bar"); - assert!("/c/world&foo=bar" > &path_and_query); - assert!(&path_and_query > "/a/world&foo=bar"); - assert!("/a/world&foo=bar" < &path_and_query); - - // by val - assert!(path_and_query < "/c/world&foo=bar"); - assert!("/c/world&foo=bar" > path_and_query); - assert!(path_and_query > "/a/world&foo=bar"); - assert!("/a/world&foo=bar" < path_and_query); - } - - #[test] - fn compares_with_a_string() { - let path_and_query: PathAndQuery = "/b/world&foo=bar".parse().unwrap(); - assert!(path_and_query < "/c/world&foo=bar".to_string()); - assert!("/c/world&foo=bar".to_string() > path_and_query); - assert!(path_and_query > "/a/world&foo=bar".to_string()); - assert!("/a/world&foo=bar".to_string() < path_and_query); - } - - #[test] - fn ignores_valid_percent_encodings() { - assert_eq!("/a%20b", pq("/a%20b?r=1").path()); - assert_eq!("qr=%31", pq("/a/b?qr=%31").query().unwrap()); - } - - #[test] - fn ignores_invalid_percent_encodings() { - assert_eq!("/a%%b", pq("/a%%b?r=1").path()); - assert_eq!("/aaa%", pq("/aaa%").path()); - assert_eq!("/aaa%", pq("/aaa%?r=1").path()); - assert_eq!("/aa%2", pq("/aa%2").path()); - assert_eq!("/aa%2", pq("/aa%2?r=1").path()); - assert_eq!("qr=%3", pq("/a/b?qr=%3").query().unwrap()); - } - - #[test] - fn allow_utf8_in_path() { - assert_eq!("/🍕", pq("/🍕").path()); - } - - #[test] - fn allow_utf8_in_query() { - assert_eq!(Some("pizza=🍕"), pq("/test?pizza=🍕").query()); - } - - #[test] - fn rejects_invalid_utf8_in_path() { - PathAndQuery::try_from(&[b'/', 0xFF][..]).expect_err("reject invalid utf8"); - } - - #[test] - fn rejects_invalid_utf8_in_query() { - PathAndQuery::try_from(&[b'/', b'a', b'?', 0xFF][..]).expect_err("reject invalid utf8"); - } - - #[test] - fn json_is_fine() { - assert_eq!( - r#"/{"bread":"baguette"}"#, - pq(r#"/{"bread":"baguette"}"#).path() - ); - } - - fn pq(s: &str) -> PathAndQuery { - s.parse().expect(&format!("parsing {}", s)) - } -} diff --git a/vendor/http/src/uri/port.rs b/vendor/http/src/uri/port.rs deleted file mode 100644 index 2a7028e2..00000000 --- a/vendor/http/src/uri/port.rs +++ /dev/null @@ -1,151 +0,0 @@ -use std::fmt; - -use super::{ErrorKind, InvalidUri}; - -/// The port component of a URI. -pub struct Port<T> { - port: u16, - repr: T, -} - -impl<T> Port<T> { - /// Returns the port number as a `u16`. - /// - /// # Examples - /// - /// Port as `u16`. - /// - /// ``` - /// # use http::uri::Authority; - /// let authority: Authority = "example.org:80".parse().unwrap(); - /// - /// let port = authority.port().unwrap(); - /// assert_eq!(port.as_u16(), 80); - /// ``` - pub const fn as_u16(&self) -> u16 { - self.port - } -} - -impl<T> Port<T> -where - T: AsRef<str>, -{ - /// Converts a `str` to a port number. - /// - /// The supplied `str` must be a valid u16. - pub(crate) fn from_str(bytes: T) -> Result<Self, InvalidUri> { - bytes - .as_ref() - .parse::<u16>() - .map(|port| Port { port, repr: bytes }) - .map_err(|_| ErrorKind::InvalidPort.into()) - } - - /// Returns the port number as a `str`. - /// - /// # Examples - /// - /// Port as `str`. - /// - /// ``` - /// # use http::uri::Authority; - /// let authority: Authority = "example.org:80".parse().unwrap(); - /// - /// let port = authority.port().unwrap(); - /// assert_eq!(port.as_str(), "80"); - /// ``` - pub fn as_str(&self) -> &str { - self.repr.as_ref() - } -} - -impl<T> fmt::Debug for Port<T> -where - T: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("Port").field(&self.port).finish() - } -} - -impl<T> fmt::Display for Port<T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // Use `u16::fmt` so that it respects any formatting flags that - // may have been set (like padding, align, etc). - fmt::Display::fmt(&self.port, f) - } -} - -impl<T> From<Port<T>> for u16 { - fn from(port: Port<T>) -> Self { - port.as_u16() - } -} - -impl<T> AsRef<str> for Port<T> -where - T: AsRef<str>, -{ - fn as_ref(&self) -> &str { - self.as_str() - } -} - -impl<T, U> PartialEq<Port<U>> for Port<T> { - fn eq(&self, other: &Port<U>) -> bool { - self.port == other.port - } -} - -impl<T> PartialEq<u16> for Port<T> { - fn eq(&self, other: &u16) -> bool { - self.port == *other - } -} - -impl<T> PartialEq<Port<T>> for u16 { - fn eq(&self, other: &Port<T>) -> bool { - other.port == *self - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn partialeq_port() { - let port_a = Port::from_str("8080").unwrap(); - let port_b = Port::from_str("8080").unwrap(); - assert_eq!(port_a, port_b); - } - - #[test] - fn partialeq_port_different_reprs() { - let port_a = Port { - repr: "8081", - port: 8081, - }; - let port_b = Port { - repr: String::from("8081"), - port: 8081, - }; - assert_eq!(port_a, port_b); - assert_eq!(port_b, port_a); - } - - #[test] - fn partialeq_u16() { - let port = Port::from_str("8080").unwrap(); - // test equals in both directions - assert_eq!(port, 8080); - assert_eq!(8080, port); - } - - #[test] - fn u16_from_port() { - let port = Port::from_str("8080").unwrap(); - assert_eq!(8080, u16::from(port)); - } -} diff --git a/vendor/http/src/uri/scheme.rs b/vendor/http/src/uri/scheme.rs deleted file mode 100644 index dbcc8c3f..00000000 --- a/vendor/http/src/uri/scheme.rs +++ /dev/null @@ -1,361 +0,0 @@ -use std::convert::TryFrom; -use std::fmt; -use std::hash::{Hash, Hasher}; -use std::str::FromStr; - -use bytes::Bytes; - -use super::{ErrorKind, InvalidUri}; -use crate::byte_str::ByteStr; - -/// Represents the scheme component of a URI -#[derive(Clone)] -pub struct Scheme { - pub(super) inner: Scheme2, -} - -#[derive(Clone, Debug)] -pub(super) enum Scheme2<T = Box<ByteStr>> { - None, - Standard(Protocol), - Other(T), -} - -#[derive(Copy, Clone, Debug)] -pub(super) enum Protocol { - Http, - Https, -} - -impl Scheme { - /// HTTP protocol scheme - pub const HTTP: Scheme = Scheme { - inner: Scheme2::Standard(Protocol::Http), - }; - - /// HTTP protocol over TLS. - pub const HTTPS: Scheme = Scheme { - inner: Scheme2::Standard(Protocol::Https), - }; - - pub(super) fn empty() -> Self { - Scheme { - inner: Scheme2::None, - } - } - - /// Return a str representation of the scheme - /// - /// # Examples - /// - /// ``` - /// # use http::uri::*; - /// let scheme: Scheme = "http".parse().unwrap(); - /// assert_eq!(scheme.as_str(), "http"); - /// ``` - #[inline] - pub fn as_str(&self) -> &str { - use self::Protocol::*; - use self::Scheme2::*; - - match self.inner { - Standard(Http) => "http", - Standard(Https) => "https", - Other(ref v) => &v[..], - None => unreachable!(), - } - } -} - -impl<'a> TryFrom<&'a [u8]> for Scheme { - type Error = InvalidUri; - #[inline] - fn try_from(s: &'a [u8]) -> Result<Self, Self::Error> { - use self::Scheme2::*; - - match Scheme2::parse_exact(s)? { - None => Err(ErrorKind::InvalidScheme.into()), - Standard(p) => Ok(Standard(p).into()), - Other(_) => { - let bytes = Bytes::copy_from_slice(s); - - // Safety: postcondition on parse_exact() means that s and - // hence bytes are valid UTF-8. - let string = unsafe { ByteStr::from_utf8_unchecked(bytes) }; - - Ok(Other(Box::new(string)).into()) - } - } - } -} - -impl<'a> TryFrom<&'a str> for Scheme { - type Error = InvalidUri; - #[inline] - fn try_from(s: &'a str) -> Result<Self, Self::Error> { - TryFrom::try_from(s.as_bytes()) - } -} - -impl FromStr for Scheme { - type Err = InvalidUri; - - fn from_str(s: &str) -> Result<Self, Self::Err> { - TryFrom::try_from(s) - } -} - -impl fmt::Debug for Scheme { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(self.as_str(), f) - } -} - -impl fmt::Display for Scheme { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(self.as_str()) - } -} - -impl AsRef<str> for Scheme { - #[inline] - fn as_ref(&self) -> &str { - self.as_str() - } -} - -impl PartialEq for Scheme { - fn eq(&self, other: &Scheme) -> bool { - use self::Protocol::*; - use self::Scheme2::*; - - match (&self.inner, &other.inner) { - (&Standard(Http), &Standard(Http)) => true, - (&Standard(Https), &Standard(Https)) => true, - (Other(a), Other(b)) => a.eq_ignore_ascii_case(b), - (&None, _) | (_, &None) => unreachable!(), - _ => false, - } - } -} - -impl Eq for Scheme {} - -/// Case-insensitive equality -/// -/// # Examples -/// -/// ``` -/// # use http::uri::Scheme; -/// let scheme: Scheme = "HTTP".parse().unwrap(); -/// assert_eq!(scheme, *"http"); -/// ``` -impl PartialEq<str> for Scheme { - fn eq(&self, other: &str) -> bool { - self.as_str().eq_ignore_ascii_case(other) - } -} - -/// Case-insensitive equality -impl PartialEq<Scheme> for str { - fn eq(&self, other: &Scheme) -> bool { - other == self - } -} - -/// Case-insensitive hashing -impl Hash for Scheme { - fn hash<H>(&self, state: &mut H) - where - H: Hasher, - { - match self.inner { - Scheme2::None => (), - Scheme2::Standard(Protocol::Http) => state.write_u8(1), - Scheme2::Standard(Protocol::Https) => state.write_u8(2), - Scheme2::Other(ref other) => { - other.len().hash(state); - for &b in other.as_bytes() { - state.write_u8(b.to_ascii_lowercase()); - } - } - } - } -} - -impl<T> Scheme2<T> { - pub(super) fn is_none(&self) -> bool { - matches!(*self, Scheme2::None) - } -} - -// Require the scheme to not be too long in order to enable further -// optimizations later. -const MAX_SCHEME_LEN: usize = 64; - -// scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) -// -// SCHEME_CHARS is a table of valid characters in the scheme part of a URI. An -// entry in the table is 0 for invalid characters. For valid characters the -// entry is itself (i.e. the entry for 43 is b'+' because b'+' == 43u8). An -// important characteristic of this table is that all entries above 127 are -// invalid. This makes all of the valid entries a valid single-byte UTF-8 code -// point. This means that a slice of such valid entries is valid UTF-8. -#[rustfmt::skip] -const SCHEME_CHARS: [u8; 256] = [ - // 0 1 2 3 4 5 6 7 8 9 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3x - 0, 0, 0, b'+', 0, b'-', b'.', 0, b'0', b'1', // 4x - b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b':', 0, // 5x - 0, 0, 0, 0, 0, b'A', b'B', b'C', b'D', b'E', // 6x - b'F', b'G', b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', // 7x - b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W', b'X', b'Y', // 8x - b'Z', 0, 0, 0, 0, 0, 0, b'a', b'b', b'c', // 9x - b'd', b'e', b'f', b'g', b'h', b'i', b'j', b'k', b'l', b'm', // 10x - b'n', b'o', b'p', b'q', b'r', b's', b't', b'u', b'v', b'w', // 11x - b'x', b'y', b'z', 0, 0, 0, b'~', 0, 0, 0, // 12x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 13x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 14x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 15x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 17x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 18x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 19x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 21x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 22x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 23x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 24x - 0, 0, 0, 0, 0, 0 // 25x -]; - -impl Scheme2<usize> { - // Postcondition: On all Ok() returns, s is valid UTF-8 - fn parse_exact(s: &[u8]) -> Result<Scheme2<()>, InvalidUri> { - match s { - b"http" => Ok(Protocol::Http.into()), - b"https" => Ok(Protocol::Https.into()), - _ => { - if s.len() > MAX_SCHEME_LEN { - return Err(ErrorKind::SchemeTooLong.into()); - } - - // check that each byte in s is a SCHEME_CHARS which implies - // that it is a valid single byte UTF-8 code point. - for &b in s { - match SCHEME_CHARS[b as usize] { - b':' => { - // Don't want :// here - return Err(ErrorKind::InvalidScheme.into()); - } - 0 => { - return Err(ErrorKind::InvalidScheme.into()); - } - _ => {} - } - } - - Ok(Scheme2::Other(())) - } - } - } - - pub(super) fn parse(s: &[u8]) -> Result<Scheme2<usize>, InvalidUri> { - if s.len() >= 7 { - // Check for HTTP - if s[..7].eq_ignore_ascii_case(b"http://") { - // Prefix will be striped - return Ok(Protocol::Http.into()); - } - } - - if s.len() >= 8 { - // Check for HTTPs - if s[..8].eq_ignore_ascii_case(b"https://") { - return Ok(Protocol::Https.into()); - } - } - - if s.len() > 3 { - for i in 0..s.len() { - let b = s[i]; - - match SCHEME_CHARS[b as usize] { - b':' => { - // Not enough data remaining - if s.len() < i + 3 { - break; - } - - // Not a scheme - if &s[i + 1..i + 3] != b"//" { - break; - } - - if i > MAX_SCHEME_LEN { - return Err(ErrorKind::SchemeTooLong.into()); - } - - // Return scheme - return Ok(Scheme2::Other(i)); - } - // Invalid scheme character, abort - 0 => break, - _ => {} - } - } - } - - Ok(Scheme2::None) - } -} - -impl Protocol { - pub(super) fn len(&self) -> usize { - match *self { - Protocol::Http => 4, - Protocol::Https => 5, - } - } -} - -impl<T> From<Protocol> for Scheme2<T> { - fn from(src: Protocol) -> Self { - Scheme2::Standard(src) - } -} - -#[doc(hidden)] -impl From<Scheme2> for Scheme { - fn from(src: Scheme2) -> Self { - Scheme { inner: src } - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn scheme_eq_to_str() { - assert_eq!(&scheme("http"), "http"); - assert_eq!(&scheme("https"), "https"); - assert_eq!(&scheme("ftp"), "ftp"); - assert_eq!(&scheme("my+funky+scheme"), "my+funky+scheme"); - } - - #[test] - fn invalid_scheme_is_error() { - Scheme::try_from("my_funky_scheme").expect_err("Unexpectedly valid Scheme"); - - // Invalid UTF-8 - Scheme::try_from([0xC0].as_ref()).expect_err("Unexpectedly valid Scheme"); - } - - fn scheme(s: &str) -> Scheme { - s.parse().expect(&format!("Invalid scheme: {}", s)) - } -} diff --git a/vendor/http/src/uri/tests.rs b/vendor/http/src/uri/tests.rs deleted file mode 100644 index 719cb94e..00000000 --- a/vendor/http/src/uri/tests.rs +++ /dev/null @@ -1,519 +0,0 @@ -use std::str::FromStr; - -use super::{ErrorKind, InvalidUri, Port, Uri, URI_CHARS}; - -#[test] -fn test_char_table() { - for (i, &v) in URI_CHARS.iter().enumerate() { - if v != 0 { - assert_eq!(i, v as usize); - } - } -} - -macro_rules! part { - ($s:expr) => { - Some(&$s.parse().unwrap()) - }; -} - -macro_rules! test_parse { - ( - $test_name:ident, - $str:expr, - $alt:expr, - $($method:ident = $value:expr,)* - ) => ( - #[test] - fn $test_name() { - let orig_str = $str; - let uri = match Uri::from_str(orig_str) { - Ok(uri) => uri, - Err(err) => { - panic!("parse error {:?} from {:?}", err, orig_str); - }, - }; - $( - assert_eq!(uri.$method(), $value, "{}: uri = {:?}", stringify!($method), uri); - )+ - assert_eq!(uri, orig_str, "partial eq to original str"); - assert_eq!(uri, uri.clone(), "clones are equal"); - - let new_str = uri.to_string(); - let new_uri = Uri::from_str(&new_str).expect("to_string output parses again as a Uri"); - assert_eq!(new_uri, orig_str, "round trip still equals original str"); - - const ALT: &'static [&'static str] = &$alt; - - for &alt in ALT.iter() { - let other: Uri = alt.parse().unwrap(); - assert_eq!(uri, *alt); - assert_eq!(uri, other); - } - } - ); -} - -test_parse! { - test_uri_parse_path_and_query, - "/some/path/here?and=then&hello#and-bye", - [], - - scheme = None, - authority = None, - path = "/some/path/here", - query = Some("and=then&hello"), - host = None, -} - -test_parse! { - test_uri_parse_absolute_form, - "http://127.0.0.1:61761/chunks", - [], - - scheme = part!("http"), - authority = part!("127.0.0.1:61761"), - path = "/chunks", - query = None, - host = Some("127.0.0.1"), - port = Port::from_str("61761").ok(), -} - -test_parse! { - test_uri_parse_absolute_form_without_path, - "https://127.0.0.1:61761", - ["https://127.0.0.1:61761/"], - - scheme = part!("https"), - authority = part!("127.0.0.1:61761"), - path = "/", - query = None, - host = Some("127.0.0.1"), - port = Port::from_str("61761").ok(), -} - -test_parse! { - test_uri_parse_asterisk_form, - "*", - [], - - scheme = None, - authority = None, - path = "*", - query = None, - host = None, -} - -test_parse! { - test_uri_parse_authority_no_port, - "localhost", - ["LOCALHOST", "LocaLHOSt"], - - scheme = None, - authority = part!("localhost"), - path = "", - query = None, - port = None, - host = Some("localhost"), -} - -test_parse! { - test_uri_authority_only_one_character_issue_197, - "S", - [], - - scheme = None, - authority = part!("S"), - path = "", - query = None, - port = None, - host = Some("S"), -} - -test_parse! { - test_uri_parse_authority_form, - "localhost:3000", - ["localhosT:3000"], - - scheme = None, - authority = part!("localhost:3000"), - path = "", - query = None, - host = Some("localhost"), - port = Port::from_str("3000").ok(), -} - -test_parse! { - test_uri_parse_absolute_with_default_port_http, - "http://127.0.0.1:80", - ["http://127.0.0.1:80/"], - - scheme = part!("http"), - authority = part!("127.0.0.1:80"), - host = Some("127.0.0.1"), - path = "/", - query = None, - port = Port::from_str("80").ok(), -} - -test_parse! { - test_uri_parse_absolute_with_default_port_https, - "https://127.0.0.1:443", - ["https://127.0.0.1:443/"], - - scheme = part!("https"), - authority = part!("127.0.0.1:443"), - host = Some("127.0.0.1"), - path = "/", - query = None, - port = Port::from_str("443").ok(), -} - -test_parse! { - test_uri_parse_fragment_questionmark, - "http://127.0.0.1/#?", - [], - - scheme = part!("http"), - authority = part!("127.0.0.1"), - host = Some("127.0.0.1"), - path = "/", - query = None, - port = None, -} - -test_parse! { - test_uri_parse_path_with_terminating_questionmark, - "http://127.0.0.1/path?", - [], - - scheme = part!("http"), - authority = part!("127.0.0.1"), - path = "/path", - query = Some(""), - port = None, -} - -test_parse! { - test_uri_parse_absolute_form_with_empty_path_and_nonempty_query, - "http://127.0.0.1?foo=bar", - [], - - scheme = part!("http"), - authority = part!("127.0.0.1"), - path = "/", - query = Some("foo=bar"), - port = None, -} - -test_parse! { - test_uri_parse_absolute_form_with_empty_path_and_fragment_with_slash, - "http://127.0.0.1#foo/bar", - [], - - scheme = part!("http"), - authority = part!("127.0.0.1"), - path = "/", - query = None, - port = None, -} - -test_parse! { - test_uri_parse_absolute_form_with_empty_path_and_fragment_with_questionmark, - "http://127.0.0.1#foo?bar", - [], - - scheme = part!("http"), - authority = part!("127.0.0.1"), - path = "/", - query = None, - port = None, -} - -test_parse! { - test_uri_parse_long_host_with_no_scheme, - "thequickbrownfoxjumpedoverthelazydogtofindthelargedangerousdragon.localhost", - [], - - scheme = None, - authority = part!("thequickbrownfoxjumpedoverthelazydogtofindthelargedangerousdragon.localhost"), - path = "", - query = None, - port = None, -} - -test_parse! { - test_uri_parse_long_host_with_port_and_no_scheme, - "thequickbrownfoxjumpedoverthelazydogtofindthelargedangerousdragon.localhost:1234", - [], - - scheme = None, - authority = part!("thequickbrownfoxjumpedoverthelazydogtofindthelargedangerousdragon.localhost:1234"), - path = "", - query = None, - port = Port::from_str("1234").ok(), -} - -test_parse! { - test_userinfo1, - "http://a:b@127.0.0.1:1234/", - [], - - scheme = part!("http"), - authority = part!("a:b@127.0.0.1:1234"), - host = Some("127.0.0.1"), - path = "/", - query = None, - port = Port::from_str("1234").ok(), -} - -test_parse! { - test_userinfo2, - "http://a:b@127.0.0.1/", - [], - - scheme = part!("http"), - authority = part!("a:b@127.0.0.1"), - host = Some("127.0.0.1"), - path = "/", - query = None, - port = None, -} - -test_parse! { - test_userinfo3, - "http://a@127.0.0.1/", - [], - - scheme = part!("http"), - authority = part!("a@127.0.0.1"), - host = Some("127.0.0.1"), - path = "/", - query = None, - port = None, -} - -test_parse! { - test_userinfo_with_port, - "user@localhost:3000", - [], - - scheme = None, - authority = part!("user@localhost:3000"), - path = "", - query = None, - host = Some("localhost"), - port = Port::from_str("3000").ok(), -} - -test_parse! { - test_userinfo_pass_with_port, - "user:pass@localhost:3000", - [], - - scheme = None, - authority = part!("user:pass@localhost:3000"), - path = "", - query = None, - host = Some("localhost"), - port = Port::from_str("3000").ok(), -} - -test_parse! { - test_ipv6, - "http://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]/", - [], - - scheme = part!("http"), - authority = part!("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]"), - host = Some("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]"), - path = "/", - query = None, - port = None, -} - -test_parse! { - test_ipv6_shorthand, - "http://[::1]/", - [], - - scheme = part!("http"), - authority = part!("[::1]"), - host = Some("[::1]"), - path = "/", - query = None, - port = None, -} - -test_parse! { - test_ipv6_shorthand2, - "http://[::]/", - [], - - scheme = part!("http"), - authority = part!("[::]"), - host = Some("[::]"), - path = "/", - query = None, - port = None, -} - -test_parse! { - test_ipv6_shorthand3, - "http://[2001:db8::2:1]/", - [], - - scheme = part!("http"), - authority = part!("[2001:db8::2:1]"), - host = Some("[2001:db8::2:1]"), - path = "/", - query = None, - port = None, -} - -test_parse! { - test_ipv6_with_port, - "http://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8008/", - [], - - scheme = part!("http"), - authority = part!("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8008"), - host = Some("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]"), - path = "/", - query = None, - port = Port::from_str("8008").ok(), -} - -test_parse! { - test_percentage_encoded_path, - "/echo/abcdefgh_i-j%20/abcdefg_i-j%20478", - [], - - scheme = None, - authority = None, - host = None, - path = "/echo/abcdefgh_i-j%20/abcdefg_i-j%20478", - query = None, - port = None, -} - -test_parse! { - test_path_permissive, - "/foo=bar|baz\\^~%", - [], - - path = "/foo=bar|baz\\^~%", -} - -test_parse! { - test_query_permissive, - "/?foo={bar|baz}\\^`", - [], - - query = Some("foo={bar|baz}\\^`"), -} - -#[test] -fn test_uri_parse_error() { - fn err(s: &str) { - Uri::from_str(s).unwrap_err(); - } - - err("http://"); - err("htt:p//host"); - err("hyper.rs/"); - err("hyper.rs?key=val"); - err("?key=val"); - err("localhost/"); - err("localhost?key=val"); - err("\0"); - err("http://[::1"); - err("http://::1]"); - err("localhost:8080:3030"); - err("@"); - err("http://username:password@/wut"); - - // illegal queries - err("/?foo\rbar"); - err("/?foo\nbar"); - err("/?<"); - err("/?>"); -} - -#[test] -fn test_max_uri_len() { - let mut uri = vec![]; - uri.extend(b"http://localhost/"); - uri.extend(vec![b'a'; 70 * 1024]); - - let uri = String::from_utf8(uri).unwrap(); - let res: Result<Uri, InvalidUri> = uri.parse(); - - assert_eq!(res.unwrap_err().0, ErrorKind::TooLong); -} - -#[test] -fn test_overflowing_scheme() { - let mut uri = vec![]; - uri.extend(vec![b'a'; 256]); - uri.extend(b"://localhost/"); - - let uri = String::from_utf8(uri).unwrap(); - let res: Result<Uri, InvalidUri> = uri.parse(); - - assert_eq!(res.unwrap_err().0, ErrorKind::SchemeTooLong); -} - -#[test] -fn test_max_length_scheme() { - let mut uri = vec![]; - uri.extend(vec![b'a'; 64]); - uri.extend(b"://localhost/"); - - let uri = String::from_utf8(uri).unwrap(); - let uri: Uri = uri.parse().unwrap(); - - assert_eq!(uri.scheme_str().unwrap().len(), 64); -} - -#[test] -fn test_uri_to_path_and_query() { - let cases = vec![ - ("/", "/"), - ("/foo?bar", "/foo?bar"), - ("/foo?bar#nope", "/foo?bar"), - ("http://hyper.rs", "/"), - ("http://hyper.rs/", "/"), - ("http://hyper.rs/path", "/path"), - ("http://hyper.rs?query", "/?query"), - ("*", "*"), - ]; - - for case in cases { - let uri = Uri::from_str(case.0).unwrap(); - let s = uri.path_and_query().unwrap().to_string(); - - assert_eq!(s, case.1); - } -} - -#[test] -fn test_authority_uri_parts_round_trip() { - let s = "hyper.rs"; - let uri = Uri::from_str(s).expect("first parse"); - assert_eq!(uri, s); - assert_eq!(uri.to_string(), s); - - let parts = uri.into_parts(); - let uri2 = Uri::from_parts(parts).expect("from_parts"); - assert_eq!(uri2, s); - assert_eq!(uri2.to_string(), s); -} - -#[test] -fn test_partial_eq_path_with_terminating_questionmark() { - let a = "/path"; - let uri = Uri::from_str("/path?").expect("first parse"); - - assert_eq!(uri, a); -} |
