diff --git a/src/common/str.rs b/src/common/str.rs index 5615560189..3f370d8549 100644 --- a/src/common/str.rs +++ b/src/common/str.rs @@ -30,6 +30,13 @@ impl ByteStr { unsafe { str::from_utf8_unchecked(self.0.as_ref()) } } + pub fn insert(&mut self, idx: usize, ch: char) { + let mut s = self.as_str().to_owned(); + s.insert(idx, ch); + let bytes = Bytes::from(s); + self.0 = bytes; + } + #[cfg(feature = "compat")] pub fn into_bytes(self) -> Bytes { self.0 diff --git a/src/uri.rs b/src/uri.rs index 36c170c8fc..9e1382a50a 100644 --- a/src/uri.rs +++ b/src/uri.rs @@ -42,7 +42,7 @@ pub struct Uri { impl Uri { /// Parse a string into a `Uri`. - fn new(s: ByteStr) -> Result { + fn new(mut s: ByteStr) -> Result { if s.len() == 0 { Err(UriError(ErrorKind::Empty)) } else if s.as_bytes() == b"*" { @@ -81,8 +81,19 @@ impl Uri { return Err(UriError(ErrorKind::Malformed)); } } + + // absolute-form must always have a path + // if there isn't a '/', for consistency, add one. + let slash = auth_end; + if s.len() == slash { + s.insert(slash, '/'); + } else if s.as_bytes()[slash] != b'/' { + s.insert(slash, '/'); + } + let query = parse_query(&s); let fragment = parse_fragment(&s); + Ok(Uri { source: s, scheme_end: scheme, @@ -443,7 +454,6 @@ macro_rules! test_parse { #[test] fn $test_name() { let uri = Uri::from_str($str).unwrap(); - println!("{:?} = {:#?}", $str, uri); $( assert_eq!(uri.$method(), $value, stringify!($method)); )+ @@ -486,6 +496,8 @@ test_parse! { query = None, fragment = None, port = Some(61761), + + to_string = "https://127.0.0.1:61761/", } test_parse! { @@ -497,6 +509,8 @@ test_parse! { path = "*", query = None, fragment = None, + + to_string = "*", } test_parse! { @@ -510,6 +524,8 @@ test_parse! { query = None, fragment = None, port = None, + + to_string = "localhost", } test_parse! { @@ -627,6 +643,8 @@ test_parse! { query = Some("foo=bar"), fragment = None, port = None, + + to_string = "http://127.0.0.1/?foo=bar", } test_parse! { @@ -651,6 +669,8 @@ test_parse! { query = None, fragment = Some("foo?bar"), port = None, + + to_string = "http://127.0.0.1/#foo?bar", } #[test]