Skip to content

Commit

Permalink
use hickory for http
Browse files Browse the repository at this point in the history
  • Loading branch information
aumetra committed Nov 12, 2024
1 parent 51fc194 commit e6b93c7
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 8 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ garde = { version = "0.20.0", features = [
"regex",
"serde",
] }
hickory-resolver = { version = "0.25.0-alpha.3", default-features = false, features = [
"dns-over-rustls",
"tokio-runtime",
] }
iso8601-timestamp = "0.3.0"
itertools = { version = "0.13.0", default-features = false }
moka = { version = "=0.12.7", features = ["sync"] }
Expand Down
1 change: 1 addition & 0 deletions crates/kitsune-http-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ bytes = "1.8.0"
futures-util = { version = "0.3.31", default-features = false, features = [
"alloc",
] }
hickory-resolver = { workspace = true }
http-body = "1.0.1"
http-body-util = "0.1.2"
http-signatures = { workspace = true }
Expand Down
32 changes: 28 additions & 4 deletions crates/kitsune-http-client/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#![doc = include_str!("../README.md")]
#![deny(missing_docs)]

use self::util::BoxCloneService;
use self::{resolver::Resolver, util::BoxCloneService};
use bytes::Buf;
use futures_util::{Stream, StreamExt};
use hickory_resolver::config::{ResolverConfig, ResolverOpts};
use http_body::Body as HttpBody;
use http_body_util::{BodyExt, BodyStream, Limited};
use hyper::{
Expand All @@ -13,7 +14,10 @@ use hyper::{
HeaderMap, Request, Response as HyperResponse, StatusCode, Uri, Version,
};
use hyper_rustls::HttpsConnectorBuilder;
use hyper_util::{client::legacy::Client as HyperClient, rt::TokioExecutor};
use hyper_util::{
client::legacy::{connect::HttpConnector, Client as HyperClient},
rt::TokioExecutor,
};
use kitsune_type::jsonld::RdfNode;
use serde::de::DeserializeOwned;
use std::{error::Error as StdError, fmt, time::Duration};
Expand All @@ -26,6 +30,7 @@ use tower_http::{
};

mod body;
mod resolver;
mod util;

type BoxBody<E = BoxError> = http_body_util::combinators::BoxBody<Bytes, E>;
Expand Down Expand Up @@ -73,6 +78,7 @@ impl StdError for Error {}
pub struct ClientBuilder {
content_length_limit: Option<usize>,
default_headers: HeaderMap,
dns_resolver: Option<Resolver>,
timeout: Option<Duration>,
}

Expand Down Expand Up @@ -113,6 +119,15 @@ impl ClientBuilder {
Ok(self)
}

/// Set a hickory DNS resolver you want thsi client to use

Check warning on line 122 in crates/kitsune-http-client/src/lib.rs

View workflow job for this annotation

GitHub Actions / Spell-check repository source

"thsi" should be "this".
///
/// Otherwise it creates a new one which connects to Quad9 via DNS-over-TLS
#[must_use]
pub fn dns_resolver(mut self, resolver: impl Into<Resolver>) -> Self {
self.dns_resolver = Some(resolver.into());
self
}

/// Set the User-Agent header
///
/// Defaults to `kitsune-http-client`
Expand Down Expand Up @@ -143,14 +158,22 @@ impl ClientBuilder {
///
/// Yes, this operation is infallible
#[must_use]
pub fn build(self) -> Client {
pub fn build(mut self) -> Client {
let resolver = self.dns_resolver.take().unwrap_or_else(|| {
let resolver = hickory_resolver::TokioResolver::tokio(
ResolverConfig::quad9_tls(),
ResolverOpts::default(),
);
resolver.into()
});

let connector = HttpsConnectorBuilder::new()
.with_native_roots()
.expect("Failed to fetch native certificates")
.https_or_http()
.enable_http1()
.enable_http2()
.build();
.wrap_connector(HttpConnector::new_with_resolver(resolver));

let client = HyperClient::builder(TokioExecutor::new())
.build(connector)
Expand Down Expand Up @@ -207,6 +230,7 @@ impl Default for ClientBuilder {
let builder = ClientBuilder {
content_length_limit: Some(DEFAULT_BODY_LIMIT),
default_headers: HeaderMap::default(),
dns_resolver: None,
timeout: Option::default(),
};

Expand Down
74 changes: 74 additions & 0 deletions crates/kitsune-http-client/src/resolver.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use futures_util::{future::BoxFuture, FutureExt};
use hickory_resolver::{lookup_ip::LookupIpIntoIter, TokioResolver};
use hyper_util::client::legacy::connect::dns::Name;
use pin_project::pin_project;
use std::{
future::Future,
net::SocketAddr,
pin::Pin,
task::{self, Poll},
};
use tower::{BoxError, Service};

pub struct ResolveIter {
inner: LookupIpIntoIter,
}

impl Iterator for ResolveIter {
type Item = SocketAddr;

#[inline]
fn next(&mut self) -> Option<Self::Item> {
let item = self.inner.next()?;
Some(SocketAddr::new(item, 80))
}
}

#[pin_project]
pub struct ResolveFut {
#[pin]
inner: BoxFuture<'static, Result<ResolveIter, BoxError>>,
}

impl Future for ResolveFut {
type Output = Result<ResolveIter, BoxError>;

fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
let this = self.project();
this.inner.poll(cx)
}
}

#[derive(Clone)]
pub struct Resolver {
inner: TokioResolver,
}

impl From<TokioResolver> for Resolver {
fn from(value: TokioResolver) -> Self {
Self { inner: value }
}
}

impl Service<Name> for Resolver {
type Error = BoxError;
type Response = ResolveIter;
type Future = ResolveFut;

fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}

fn call(&mut self, req: Name) -> Self::Future {
let dns_client = self.inner.clone();
let inner = async move {
let lookup_ips = dns_client.lookup_ip(req.as_str()).await?;
Ok(ResolveIter {
inner: lookup_ips.into_iter(),
})
}
.boxed();

ResolveFut { inner }
}
}
5 changes: 1 addition & 4 deletions lib/geomjeungja/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ license = "MIT OR Apache-2.0"

[dependencies]
async-trait = "0.1.83"
hickory-resolver = { version = "0.25.0-alpha.3", default-features = false, features = [
"dns-over-rustls",
"tokio-runtime",
] }
hickory-resolver = { workspace = true }
rand = "0.8.5"
serde = { version = "1.0.214", features = ["derive"] }
simdutf8 = { workspace = true }
Expand Down

0 comments on commit e6b93c7

Please sign in to comment.