将 `http::uri::Uri` 的主机解析为 IP 地址
我有一个 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
语法!但该实现需要一个端口,如果没有则失败。
所以是的,我还没有找到一种简单的方法来做到这一点。但看来这应该没那么难!有什么想法吗?
I have an http::uri::Uri
value and I want to get the IpAddr
s of the host. In case the host is an IP address (e.g. http://127.0.0.1:8080
), it just needs to be parsed. But if it's a hostname, it needs to be DNS resolved. How do I best do that?
It seems like std
only has one public way to resolve hosts: ToSocketAddrs
. Unfortunately, it includes the port in the API which is irrelevant for DNS resolving. But oh well. But with this, my first attempt was thus:
use std::net::ToSocketAddr;
let host = uri.authority().unwrap().host();
let addresses = (host, 0).to_socket_addrs()?
.map(|socket_addr| socket_addr.ip());
(I am using a dummy port here since it's irrelevant for the DNS resolution.)
This attempt works for many cases, but not for the square-bracket IPv6 form: http://[::1]:8080
. Here, host()
is [::1]
and is not parsable as IpAddr
, thus to_socket_addrs()
tries to resolve [::1]
as host, which fails. So I would need to check manually whether the host is an IPv6 within square-brackets. Not nice, especially since I don't know what grammars are allowed here exactly.
I had several other ideas, like changing the Authority
to always have a dummy port, because then I could call authority.as_str().to_socket_addrs()
. The <&str as ToSocketAddr>
does support the [::1]:8080
syntax! But that impl NEEDS a port and fails if there is none.
So yes, I have not found an easy way to do that. But it seems this should not be that hard! Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
尝试将其解析为
std::net:首先:IpAddr
,如果失败则查找主机名。您必须自己处理方括号表示法,但这还不错:(游乐场)
如果返回
None
则解析失败,下一步是尝试通过 DNS 将该字符串解析为主机名。Try parsing it as
std::net::IpAddr
first, then look up the hostname if that fails. You have to handle the square bracket notation yourself, but this isn't too bad:(Playground)
If this returns
None
then parsing failed, and the next step is to attempt to resolve the string as a hostname through DNS.