我有一个http::uri::Uri值,我想得到主机的IpAddr。如果主机是IP地址(例如http://127.0.0.1:8080),则只需对其进行解析。但是如果是主机名,则需要解析DNS。我该怎么做呢?
std似乎只有一种解析主机的公共方式:ToSocketAddrs。不幸的是,它在API中包含了与DNS解析无关的端口。但是哦,好吧。但这样做,我的第一次尝试是:
use std::net::ToSocketAddr;
let host = uri.authority().unwrap().host();
let addresses = (host, 0).to_socket_addrs()?
.map(|socket_addr| socket_addr.ip());(这里我使用的是一个虚拟端口,因为它与DNS解析无关。)
这种尝试适用于许多情况,但不适用于方括号IPv6表单:http://[::1]:8080。在这里,host()是[::1],不能解析为IpAddr,因此to_socket_addrs()试图将[::1]解析为主机,但失败了。因此,我需要手动检查主机是否为方括号内的IPv6。不太好,特别是因为我不知道这里到底允许什么语法。
我还有其他一些想法,比如将Authority更改为始终有一个虚拟端口,因为这样我就可以调用authority.as_str().to_socket_addrs()了。<&str as ToSocketAddr>确实支持[::1]:8080语法!但这一推动力需要一个港口,如果没有港口,就会失败。
所以,是的,我还没有找到一个简单的方法来做到这一点。但这似乎没那么难!有什么想法吗?
发布于 2022-03-15 12:02:00
尝试将其解析为std::net::IpAddr,如果失败,则查找主机名。您必须自己处理方括号表示法,但这并不是太糟糕:
use std::net::IpAddr;
fn parse_ip_from_uri_host(host: &str) -> Option<IpAddr> {
host.parse::<IpAddr>().ok().or_else(||
// Parsing failed, try as bracketed IPv6
host.strip_prefix("[")?
.strip_suffix("]")?
.parse::<IpAddr>().ok()
)
}(游乐场)
如果返回None,则解析失败,下一步是尝试通过DNS将字符串解析为主机名。
https://stackoverflow.com/questions/71481475
复制相似问题