Skip to content

Commit

Permalink
managing returned iterators
Browse files Browse the repository at this point in the history
  • Loading branch information
jmwample committed Jan 22, 2025
1 parent 8fd1d4e commit 0773119
Showing 1 changed file with 37 additions and 10 deletions.
47 changes: 37 additions & 10 deletions common/http-api-client/src/dns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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?
}
};

Expand All @@ -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> {
Expand Down Expand Up @@ -146,7 +161,7 @@ mod test {
.unwrap();

let resp = client
.get("http://ifconfig.me")
.get("http://ifconfig.me:80")
.send()
.await
.unwrap()
Expand All @@ -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(())
}
}

0 comments on commit 0773119

Please sign in to comment.