Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow % in IPv6 addresses to support zone identifiers. #343

Merged
merged 2 commits into from Oct 7, 2019
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 17 additions & 2 deletions src/uri/authority.rs
Expand Up @@ -103,15 +103,20 @@ impl Authority {
}
b':' => {
colon_cnt += 1;
},
}
b'[' => {
start_bracket = true;
if has_percent {
// Something other than the userinfo has a `%`, so reject it.
return Err(ErrorKind::InvalidAuthority.into());
ComputerDruid marked this conversation as resolved.
Show resolved Hide resolved
}
}
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 @@ -127,8 +132,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 @@ -612,4 +620,11 @@ 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);
}
}