diff --git a/common/http-api-client/src/dns.rs b/common/http-api-client/src/dns.rs index 3052f8eb0e..f0b6503c73 100644 --- a/common/http-api-client/src/dns.rs +++ b/common/http-api-client/src/dns.rs @@ -15,6 +15,7 @@ use std::fmt; use std::net::SocketAddr; use std::sync::Arc; +use hickory_resolver::lookup_ip::LookupIp; use hickory_resolver::{ config::{LookupIpStrategy, NameServerConfigGroup, ResolverConfig, ResolverOpts}, error::ResolveError, @@ -51,26 +52,19 @@ pub struct HickoryDnsResolver { impl Resolve for HickoryDnsResolver { fn resolve(&self, name: Name) -> Resolving { - self.resolve_str(name.as_str()) - } -} - -impl HickoryDnsResolver { - pub fn resolve_str(&self, name: &str) -> Resolving { let resolver = self.state.clone(); let fallback = self.fallback.clone(); - let domain = name.to_owned(); Box::pin(async move { let resolver = resolver.get_or_try_init(new_resolver)?; // try the primary DNS resolver that we set up (DoH or DoT or whatever) - let lookup = match resolver.lookup_ip(&domain).await { + let lookup = match resolver.lookup_ip(name.as_str()).await { Ok(res) => res, Err(e) => { // on failure use the fall back system configured DNS resolver warn!("primary DNS failed w/ error {e}: using system fallback"); let resolver = fallback.get_or_try_init(new_resolver_system)?; - resolver.lookup_ip(&domain).await? + resolver.lookup_ip(name.as_str()).await? } }; @@ -90,6 +84,27 @@ impl Iterator for SocketAddrs { } } +type BoxError = Box; + +impl HickoryDnsResolver { + pub async fn resolve_str(&self, name: &str) -> Result { + let resolver = self.state.get_or_try_init(new_resolver)?; + + // try the primary DNS resolver that we set up (DoH or DoT or whatever) + let lookup = match resolver.lookup_ip(name).await { + Ok(res) => res, + Err(e) => { + // on failure use the fall back system configured DNS resolver + warn!("primary DNS failed w/ error {e}: using system fallback"); + let resolver = self.fallback.get_or_try_init(new_resolver_system)?; + resolver.lookup_ip(name).await? + } + }; + + Ok(lookup) + } +} + /// Create a new resolver with a custom DoT based configuration. The options are overridden to look /// up for both IPv4 and IPv6 addresses to work with "happy eyeballs" algorithm. fn new_resolver() -> Result { @@ -146,7 +161,7 @@ mod test { .unwrap(); let resp = client - .get("http://ifconfig.me") + .get("http://ifconfig.me:80") .send() .await .unwrap() @@ -156,4 +171,16 @@ mod test { assert!(!resp.is_empty()); } + + #[tokio::test] + async fn dns_lookup() -> Result<(), BoxError> { + let resolver = HickoryDnsResolver::default(); + + let domain = "ifconfig.me"; + let addrs = resolver.resolve_str(domain).await?; + + assert!(addrs.into_iter().next().is_some()); + + Ok(()) + } }