Skip to content

Commit

Permalink
Allow % in IPv6 addresses to support zone identifiers. (#343)
Browse files Browse the repository at this point in the history
https://tools.ietf.org/html/rfc6874 explains that %25 can be used to
indicate a "zone identifier", useful for IPv6 link-local addresses.
  • Loading branch information
ComputerDruid authored and seanmonstar committed Nov 25, 2019
1 parent 8775094 commit d035ed5
Showing 1 changed file with 25 additions and 1 deletion.
26 changes: 25 additions & 1 deletion src/uri/authority.rs
Expand Up @@ -101,12 +101,17 @@ impl Authority {
}
b'[' => {
start_bracket = true;
if has_percent {
// Something other than the userinfo has a `%`, so reject it.
return Err(ErrorKind::InvalidAuthority.into());
}
}
b']' => {
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);
Expand All @@ -122,8 +127,11 @@ impl Authority {
// 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 will fail with an error.
// was part of the hostname (and not part of an IPv6 address), and
// will fail with an error.
has_percent = true;
}
0 => {
Expand Down Expand Up @@ -641,4 +649,20 @@ mod tests {
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 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);
}
}

0 comments on commit d035ed5

Please sign in to comment.