Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 19 additions & 11 deletions src/uri/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -802,10 +802,16 @@ fn parse_full(mut s: Bytes) -> Result<Uri, InvalidUri> {
}
Scheme2::Other(n) => {
// Grab the protocol
let mut scheme = s.split_to(n + 3);
let scheme = s.split_to(n);

// Strip ://, TODO: truncate
let _ = scheme.split_off(n);
// Remove ":" or "://" but not ":/"
if s[1] == b'/' && s[2] == b'/' {
// Remove "://"
let _ = s.split_to(3);
} else {
// Remove ":"
let _ = s.split_to(1);
}

// Allocate the ByteStr
let val = unsafe { ByteStr::from_utf8_unchecked(scheme) };
Expand Down Expand Up @@ -834,16 +840,16 @@ fn parse_full(mut s: Bytes) -> Result<Uri, InvalidUri> {
});
}

// 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) },
};

if authority.as_str().len() == 0 && s.len() == 0 {
// Neither path nor authority present.
return Err(ErrorKind::InvalidFormat.into());
}

Ok(Uri {
scheme: scheme.into(),
authority: authority,
Expand Down Expand Up @@ -901,11 +907,13 @@ impl PartialEq<str> for Uri {

other = &other[scheme.len()..];

if &other[..3] != b"://" {
if &other[..3] == b"://" {
other = &other[3..];
} else if &other[..1] == b":" {
other = &other[1..];
} else {
return false;
}

other = &other[3..];
}

if let Some(auth) = self.authority() {
Expand Down
18 changes: 9 additions & 9 deletions src/uri/scheme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,30 +281,30 @@ impl Scheme2<usize> {
}
}

if s.len() > 3 {
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"//" {
// According to https://tools.ietf.org/html/rfc3986#section-3 the URI "x:"
// has scheme "x", but to differentiate from shortcuts like
// "localhost:3000", which should be handled equivalent to
// "http://localhost:3000" we only treat an URI part as a scheme if the ':'
// is followed by a '/'.
if (i + 1) >= s.len() || s[i + 1] != b'/' {
break;
}

// Check length
if i > MAX_SCHEME_LEN {
return Err(ErrorKind::SchemeTooLong.into());
}

// Return scheme
return Ok(Scheme2::Other(i));
}
// Invald scheme character, abort
// Invalid scheme character, abort
0 => break,
_ => {}
}
Expand Down
28 changes: 28 additions & 0 deletions src/uri/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,34 @@ test_parse! {
port = Port::from_str("1234").ok(),
}

test_parse! {
test_uri_parse_scheme_single_slash,
"x:/y",
[],

scheme = part!("x"),
path = "/y",
}

test_parse! {
test_uri_parse_scheme_triple_slash,
"x:///y",
[],

scheme = part!("x"),
path = "/y",
}


test_parse! {
test_uri_parse_scheme_file,
"file:/foo/bar",
["file:///foo/bar"],

scheme = part!("file"),
path = "/foo/bar",
}

test_parse! {
test_userinfo1,
"http://a:[email protected]:1234/",
Expand Down