#![deny(missing_docs)]
#![deny(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
#![cfg_attr(test, allow(clippy::expect_used, clippy::unwrap_used, clippy::panic))]
#![cfg_attr(target_arch = "wasm32", allow(dead_code))]
#[cfg(not(any(
feature = "tokio",
feature = "smol",
feature = "compio",
feature = "wasm",
feature = "wasi-p2",
doc
)))]
compile_error!(
"aioduct: enable at least one runtime feature: tokio, smol, compio, wasm, or wasi-p2"
);
#[cfg(all(feature = "http3", not(feature = "rustls")))]
compile_error!("aioduct: the `http3` feature currently requires the `rustls` TLS backend feature");
pub mod bandwidth;
pub mod body;
pub mod cache;
mod clock;
pub mod cookie;
mod decompress;
mod digest_auth;
pub mod error;
pub mod forwarded;
pub(crate) mod h2c_probe;
pub mod hsts;
pub mod http2;
pub mod link;
pub mod middleware;
pub mod multipart;
pub mod netrc;
pub mod observer;
pub mod proxy;
pub mod redirect;
pub mod retry;
pub mod sse;
pub mod throttle;
pub mod timing;
pub mod traits;
#[cfg(feature = "json")]
pub mod problem;
#[cfg(feature = "blocking")]
pub mod blocking;
#[cfg(not(target_arch = "wasm32"))]
pub mod chunk_download;
#[cfg(not(target_arch = "wasm32"))]
pub mod client;
#[cfg(feature = "tower")]
pub mod connector;
#[cfg(not(target_arch = "wasm32"))]
pub mod forward;
#[cfg(not(target_arch = "wasm32"))]
mod happy_eyeballs;
#[cfg(feature = "hickory-dns")]
pub mod hickory;
#[cfg(not(target_arch = "wasm32"))]
pub(crate) mod pool;
#[cfg(not(target_arch = "wasm32"))]
pub mod request;
#[cfg(not(target_arch = "wasm32"))]
pub mod response;
#[cfg(not(target_arch = "wasm32"))]
pub mod runtime;
#[cfg(not(target_arch = "wasm32"))]
mod socks4;
#[cfg(not(target_arch = "wasm32"))]
mod socks5;
#[cfg(not(target_arch = "wasm32"))]
mod timeout;
#[cfg(not(target_arch = "wasm32"))]
pub mod tls;
#[cfg(not(target_arch = "wasm32"))]
pub mod upgrade;
#[cfg(feature = "wasm")]
pub mod wasm;
#[cfg(feature = "wasi-p2")]
pub mod wasi_p2;
#[cfg(feature = "tracing")]
mod tracing_middleware;
#[cfg(feature = "tracing")]
pub use tracing_middleware::TracingMiddleware;
#[cfg(feature = "otel")]
mod otel_middleware;
#[cfg(feature = "otel")]
pub use otel_middleware::OtelMiddleware;
#[cfg(all(feature = "http3", feature = "rustls"))]
mod alt_svc;
#[cfg(all(feature = "http3", feature = "rustls"))]
#[path = "h3/mod.rs"]
pub mod h3_transport;
pub use bandwidth::BandwidthLimiter;
pub use body::{BodyStreamSend, RequestBody};
pub use cache::{CacheConfig, CacheEntry, CacheStore, HttpCache, InMemoryCacheStore};
pub use cookie::{Cookie, CookieJar, SameSite};
pub use error::{Error, SendError};
pub use forwarded::ForwardedElement;
pub use hsts::HstsStore;
pub use http2::Http2Config;
pub use link::Link;
pub use middleware::Middleware;
pub use multipart::{Multipart, Part};
pub use netrc::{Netrc, NetrcMiddleware};
pub use observer::{
ConnectionEvent, ConnectionPhase, NegotiatedProtocol, PoolOutcome, RequestEvent,
RequestObserver, RequestPhase, TransferDirection,
};
pub use proxy::{NoProxy, ProxyConfig, ProxySettings};
pub use redirect::{RedirectAction, RedirectPolicy};
pub use retry::{RetryBudget, RetryConfig};
#[cfg(not(target_arch = "wasm32"))]
pub use sse::SseStreamLocal;
pub use sse::{SseDecoder, SseEvent, SseMessage, SseStream, SseStreamSend};
pub use throttle::RateLimiter;
#[allow(deprecated)]
pub use timing::RequestTimings;
pub use traits::{HttpClient, RequestBuilderExt, ResponseExt};
#[cfg(feature = "json")]
pub use problem::ProblemDetails;
#[cfg(not(target_arch = "wasm32"))]
pub use chunk_download::ChunkDownload;
#[cfg(not(target_arch = "wasm32"))]
pub use chunk_download::ChunkDownloadLocal;
#[cfg(not(target_arch = "wasm32"))]
pub use client::HttpEngineBuilder;
#[cfg(not(target_arch = "wasm32"))]
pub use client::HttpEngineCore;
#[cfg(not(target_arch = "wasm32"))]
pub use client::HttpEngineLocal;
#[cfg(not(target_arch = "wasm32"))]
pub use client::HttpEngineSend;
#[cfg(not(target_arch = "wasm32"))]
pub use forward::ForwardBuilder;
#[cfg(not(target_arch = "wasm32"))]
pub use forward::forward_local::ForwardBuilderLocal;
#[cfg(feature = "hickory-dns")]
pub use hickory::HickoryResolver;
#[cfg(not(target_arch = "wasm32"))]
pub use request::RequestBuilderLocal;
#[cfg(not(target_arch = "wasm32"))]
pub use request::RequestBuilderSend;
#[cfg(not(target_arch = "wasm32"))]
#[deprecated(since = "0.2.0", note = "Renamed to `RequestBuilderSend`")]
pub type RequestBuilder<'a, R, C> = RequestBuilderSend<'a, R, C>;
#[cfg(not(target_arch = "wasm32"))]
pub use response::Response;
#[cfg(not(target_arch = "wasm32"))]
#[allow(deprecated)]
pub use runtime::Runtime;
#[cfg(not(target_arch = "wasm32"))]
pub use runtime::{
ConnectorLocal, ConnectorSend, Resolve, RuntimeCompletion, RuntimeLocal, RuntimePoll,
SocketConfig,
};
#[cfg(feature = "wasi-p2")]
pub use traits::OwnedWasiRequestBuilder;
#[cfg(feature = "wasm")]
pub use traits::OwnedWasmRequestBuilder;
#[cfg(not(target_arch = "wasm32"))]
pub use traits::{OwnedRequestBuilderLocal, OwnedRequestBuilderSend};
#[cfg(not(target_arch = "wasm32"))]
#[deprecated(since = "0.2.0", note = "Renamed to `OwnedRequestBuilderSend`")]
pub type OwnedRequestBuilder<R, C> = OwnedRequestBuilderSend<R, C>;
#[cfg(not(target_arch = "wasm32"))]
pub use upgrade::Upgraded;
#[cfg(not(target_arch = "wasm32"))]
pub use upgrade::UpgradedLocal;
#[cfg(feature = "tokio")]
pub type TokioClient =
HttpEngineSend<runtime::tokio_rt::TokioRuntime, runtime::tokio_rt::TcpConnector>;
#[cfg(feature = "tokio")]
pub type TokioEngine = TokioClient;
#[cfg(feature = "smol")]
pub type SmolClient = HttpEngineSend<runtime::smol_rt::SmolRuntime, runtime::smol_rt::TcpConnector>;
#[cfg(feature = "smol")]
pub type SmolEngine = SmolClient;
#[cfg(feature = "compio")]
pub type CompioClient =
HttpEngineLocal<runtime::compio_rt::CompioRuntime, runtime::compio_rt::TcpConnector>;
#[cfg(feature = "compio")]
pub type CompioEngine = CompioClient;
#[cfg(feature = "wasm")]
pub type WasmClient = wasm::WasmClient;
#[cfg(feature = "wasi-p2")]
pub type WasiClient = wasi_p2::WasiClient;
#[cfg(all(feature = "blocking", feature = "tokio"))]
pub type BlockingTokioClient =
blocking::BlockingClient<TokioClient, runtime::tokio_rt::TokioRuntime>;
#[cfg(all(feature = "blocking", feature = "smol"))]
pub type BlockingSmolClient = blocking::BlockingClient<SmolClient, runtime::smol_rt::SmolRuntime>;
#[cfg(all(feature = "blocking", feature = "compio"))]
pub type BlockingCompioClient =
blocking::BlockingClient<CompioClient, runtime::compio_rt::CompioRuntime>;
#[cfg(not(target_arch = "wasm32"))]
pub use tls::TlsInfo;
#[cfg(not(target_arch = "wasm32"))]
pub use tls::TlsVersion;
#[cfg(feature = "rustls")]
pub use tls::{Certificate, Identity};
pub use http::{HeaderMap, Method, StatusCode, Uri, Version};
#[cfg(not(target_arch = "wasm32"))]
pub use hyper::ext::Protocol;
#[cfg(feature = "__bench")]
#[doc(hidden)]
#[allow(clippy::expect_used, clippy::unwrap_used)]
pub mod __bench {
use std::net::{IpAddr, SocketAddr};
use std::time::Duration;
use crate::body::RequestBodySend;
use crate::pool::{ConnectionPool, PoolKey, PooledConnection};
use crate::runtime::TokioRuntime;
use http::uri::{Authority, Scheme};
pub struct BenchPool(ConnectionPool<RequestBodySend>);
pub struct BenchConn(Option<PooledConnection<RequestBodySend>>);
pub struct BenchKey(PoolKey);
pub fn new_pool(max_idle: usize, timeout: Duration) -> BenchPool {
BenchPool(ConnectionPool::new_no_reaper(max_idle, timeout))
}
pub async fn make_h2_conn() -> BenchConn {
use crate::runtime::tokio_rt::TokioIo;
let (client_io, server_io) = tokio::io::duplex(65536);
tokio::spawn(async move {
use hyper::server::conn::http2::Builder;
use hyper::service::service_fn;
let io = TokioIo::new(server_io);
let _ = Builder::new(crate::runtime::executor::poll_executor::<TokioRuntime>())
.serve_connection(
io,
service_fn(|_req| async {
Ok::<_, std::convert::Infallible>(hyper::Response::new(
http_body_util::Empty::<bytes::Bytes>::new(),
))
}),
)
.await;
});
let io = TokioIo::new(client_io);
let (sender, conn) = hyper::client::conn::http2::handshake(
crate::runtime::executor::poll_executor::<TokioRuntime>(),
io,
)
.await
.expect("h2 handshake");
tokio::spawn(async move {
let _ = conn.await;
});
BenchConn(Some(PooledConnection::new_h2(sender)))
}
pub fn pool_key(host: &str) -> BenchKey {
BenchKey(PoolKey::new(
Scheme::HTTPS,
host.parse::<Authority>().unwrap(),
))
}
pub fn set_sans(conn: &mut BenchConn, sans: Vec<String>) {
if let Some(c) = conn.0.as_mut() {
c.sans = std::sync::Arc::from(sans);
}
}
pub fn set_remote_addr(conn: &mut BenchConn, addr: SocketAddr) {
if let Some(c) = conn.0.as_mut() {
c.remote_addr = Some(addr);
}
}
pub fn checkin(pool: &BenchPool, key: BenchKey, conn: BenchConn) {
if let Some(c) = conn.0 {
pool.0.checkin(key.0, c);
}
}
pub fn checkout_coalesced(
pool: &BenchPool,
target_host: &str,
resolved_ip: Option<IpAddr>,
) -> bool {
pool.0
.checkout_coalesced(target_host, resolved_ip)
.is_some()
}
pub fn checkout(pool: &BenchPool, key: &BenchKey) -> Option<BenchConn> {
pool.0.checkout(&key.0).map(|c| BenchConn(Some(c)))
}
pub fn wrap_read_timeout_body(
body: crate::body::RequestBodySend,
duration: Duration,
) -> crate::body::RequestBodySend {
use http_body_util::BodyExt;
crate::timeout::ReadTimeoutBody::<_, TokioRuntime>::new(body, duration)
.map_err(|e| e)
.boxed_unsync()
}
pub fn wrap_bandwidth_body(
body: crate::body::RequestBodySend,
limiter: crate::bandwidth::BandwidthLimiter,
) -> crate::body::RequestBodySend {
use http_body_util::BodyExt;
crate::bandwidth::BandwidthBody::<_, TokioRuntime>::new(body, limiter).boxed_unsync()
}
pub fn make_full_body(total_size: usize) -> crate::body::RequestBodySend {
use http_body_util::BodyExt;
http_body_util::Full::new(bytes::Bytes::from(vec![b'X'; total_size]))
.map_err(|never| match never {})
.boxed_unsync()
}
}