managing returned iterators

This commit is contained in:
jmwample
2025-01-22 14:14:04 -07:00
parent c964c137f4
commit 117eb83a0b
+37 -10
View File
@@ -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<dyn std::error::Error + Send + Sync>;
impl HickoryDnsResolver {
pub async fn resolve_str(&self, name: &str) -> Result<LookupIp, BoxError> {
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<TokioAsyncResolver, HickoryDnsSystemConfError> {
@@ -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(())
}
}