将 `http::uri::Uri` 的主机解析为 IP 地址
Resolve host of `http::uri::Uri` to IP addresses
我有一个 http::uri::Uri
值,我想获取主机的 IpAddr
。如果主机是 IP 地址(例如 http://127.0.0.1:8080
),则只需要对其进行解析。但如果是主机名,则需要进行 DNS 解析。我该怎么做最好?
似乎 std
只有一种 public 方法来解析主机: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
语法!但是如果有none.
,那意味着需要一个端口并且失败
是的,我还没有找到一种简单的方法来做到这一点。但这似乎不应该那么难!有什么想法吗?
首先尝试将其解析为 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()
)
}
如果这样 returns None
则解析失败,下一步是尝试通过 DNS 将字符串解析为主机名。
我有一个 http::uri::Uri
值,我想获取主机的 IpAddr
。如果主机是 IP 地址(例如 http://127.0.0.1:8080
),则只需要对其进行解析。但如果是主机名,则需要进行 DNS 解析。我该怎么做最好?
似乎 std
只有一种 public 方法来解析主机: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
语法!但是如果有none.
是的,我还没有找到一种简单的方法来做到这一点。但这似乎不应该那么难!有什么想法吗?
首先尝试将其解析为 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()
)
}
如果这样 returns None
则解析失败,下一步是尝试通过 DNS 将字符串解析为主机名。