mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-24 13:16:28 +00:00
fix(notify): parse IPv6 hosts without ports (#3000)
Co-authored-by: Henry Guo <marshawcoco@users.noreply.github.com>
This commit is contained in:
@@ -98,16 +98,46 @@ pub fn parse_host(s: &str) -> Result<Host, NetError> {
|
|||||||
true
|
true
|
||||||
};
|
};
|
||||||
|
|
||||||
// Split host and port, similar to net.SplitHostPort.
|
let (host, port) = if let Some(rest) = s.strip_prefix('[') {
|
||||||
let (host_str, port_str) = s.rsplit_once(':').map_or((s, ""), |(h, p)| (h, p));
|
let Some(end) = rest.find(']') else {
|
||||||
let port = if !port_str.is_empty() {
|
return Err(NetError::MissingBracket);
|
||||||
Some(port_str.parse().map_err(|_| NetError::ParseError(port_str.to_string()))?)
|
};
|
||||||
} else {
|
let host = rest[..end].to_string();
|
||||||
None
|
let port_str = &rest[end + 1..];
|
||||||
};
|
let port = if let Some(port_str) = port_str.strip_prefix(':') {
|
||||||
|
if port_str.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(port_str.parse().map_err(|_| NetError::ParseError(port_str.to_string()))?)
|
||||||
|
}
|
||||||
|
} else if port_str.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
return Err(NetError::InvalidHost);
|
||||||
|
};
|
||||||
|
|
||||||
// Trim IPv6 brackets if present.
|
(host, port)
|
||||||
let host = trim_ipv6(host_str)?;
|
} else {
|
||||||
|
if s.contains(']') {
|
||||||
|
return Err(NetError::MissingBracket);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A host with multiple colons is an IPv6 literal, optionally with a
|
||||||
|
// zone identifier. Unbracketed IPv6 with port is ambiguous, so callers
|
||||||
|
// must use the standard bracketed form when they need a port.
|
||||||
|
let (host_str, port_str) = if s.matches(':').count() > 1 {
|
||||||
|
(s, "")
|
||||||
|
} else {
|
||||||
|
s.rsplit_once(':').map_or((s, ""), |(h, p)| (h, p))
|
||||||
|
};
|
||||||
|
let port = if !port_str.is_empty() {
|
||||||
|
Some(port_str.parse().map_err(|_| NetError::ParseError(port_str.to_string()))?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
(trim_ipv6(host_str)?, port)
|
||||||
|
};
|
||||||
|
|
||||||
// Handle IPv6 zone identifier.
|
// Handle IPv6 zone identifier.
|
||||||
let trimmed_host = host.split('%').next().unwrap_or(&host);
|
let trimmed_host = host.split('%').next().unwrap_or(&host);
|
||||||
@@ -409,6 +439,33 @@ mod tests {
|
|||||||
assert_eq!(host.port, Some(8080));
|
assert_eq!(host.port, Some(8080));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_host_with_bare_ipv6_without_port() {
|
||||||
|
let result = parse_host("::1");
|
||||||
|
assert!(result.is_ok());
|
||||||
|
let host = result.unwrap();
|
||||||
|
assert_eq!(host.name, "::1");
|
||||||
|
assert_eq!(host.port, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_host_with_ipv6_zone_without_port() {
|
||||||
|
let result = parse_host("fe80::1%eth0");
|
||||||
|
assert!(result.is_ok());
|
||||||
|
let host = result.unwrap();
|
||||||
|
assert_eq!(host.name, "fe80::1%eth0");
|
||||||
|
assert_eq!(host.port, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_host_with_bracketed_ipv6_without_port() {
|
||||||
|
let result = parse_host("[::1]");
|
||||||
|
assert!(result.is_ok());
|
||||||
|
let host = result.unwrap();
|
||||||
|
assert_eq!(host.name, "::1");
|
||||||
|
assert_eq!(host.port, None);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_host_with_invalid_ipv6_missing_bracket() {
|
fn parse_host_with_invalid_ipv6_missing_bracket() {
|
||||||
let result = parse_host("::1]:8080");
|
let result = parse_host("::1]:8080");
|
||||||
|
|||||||
Reference in New Issue
Block a user