axum_proxy/
client.rs

1//! Includes helper functions to build [`Client`]s, and some re-exports from [`hyper::client`] or
2//! [`hyper_tls`].
3//!
4use hyper::body::Body as HttpBody;
5#[cfg(feature = "__rustls")]
6#[cfg_attr(docsrs, doc(cfg(feature = "rustls")))]
7pub use hyper_rustls::HttpsConnector as RustlsConnector;
8#[cfg(feature = "https")]
9#[cfg_attr(docsrs, doc(cfg(feature = "https")))]
10pub use hyper_tls::HttpsConnector;
11#[cfg(feature = "nativetls")]
12#[cfg_attr(docsrs, doc(cfg(feature = "nativetls")))]
13pub use hyper_tls::HttpsConnector as NativeTlsConnector;
14use hyper_util::client::legacy::connect::Connect;
15pub use hyper_util::client::legacy::connect::HttpConnector;
16pub use hyper_util::client::legacy::{Builder, Client};
17
18/// Default [`Builder`].
19#[must_use]
20pub fn builder() -> Builder {
21    Builder::new(hyper_util::rt::TokioExecutor::new())
22}
23
24/// Same as [`Client::new()`], except for the `B` parameter.
25#[must_use]
26pub fn http_default<B>() -> Client<HttpConnector, B>
27where
28    B: HttpBody + Send,
29    B::Data: Send,
30{
31    Builder::new(hyper_util::rt::TokioExecutor::new()).build_http()
32}
33
34/// Alias to [`nativetls_default()`].
35#[cfg(any(feature = "https", feature = "nativetls"))]
36#[cfg_attr(docsrs, doc(cfg(any(feature = "https", feature = "nativetls"))))]
37#[inline]
38#[must_use]
39pub fn https_default<B>() -> Client<NativeTlsConnector<HttpConnector>, B>
40where
41    B: HttpBody + Send,
42    B::Data: Send,
43{
44    nativetls_default()
45}
46
47/// With the default [`hyper_tls::HttpsConnector`].
48#[cfg(feature = "nativetls")]
49#[cfg_attr(docsrs, doc(cfg(feature = "nativetls")))]
50#[must_use]
51pub fn nativetls_default<B>() -> Client<NativeTlsConnector<HttpConnector>, B>
52where
53    B: HttpBody + Send,
54    B::Data: Send,
55{
56    Builder::new(hyper_util::rt::TokioExecutor::new()).build(NativeTlsConnector::new())
57}
58
59/// With the default [`hyper_rustls::HttpsConnector`].
60///
61/// The config is determined as follows. I think the cert root is similar to the `reqwest` crate.
62///
63/// 1. Cert roots
64///
65/// - if the feature `rustls-webpki-roots` is enabled, then use
66///   [`HttpsConnector::with_webpki_roots()`](hyper_rustls::HttpsConnector::with_webpki_roots());
67/// - if `rustls-webpki-roots` is disabled and `rustls-native-roots` enabled, then
68///   [`HttpsConnector::with_native_roots()`](hyper_rustls::HttpsConnector::with_native_roots());
69/// - otherwise compilation fails.
70///
71/// The feature `rustls` is equivalent to `rustls-webpki-roots`.
72///
73/// 2. Scheme
74///
75/// HTTPS only
76///
77/// 3. HTTP version
78///
79/// - if the feature `http1` is enabled, then call
80///   [`HttpsConnector::enable_http1()`](hyper_rustls::HttpsConnector::enable_http1());
81/// - if the feature `rustls-http2` is enabled, then call
82///   [`HttpsConnector::enable_http2()`](hyper_rustls::HttpsConnector::enable_http2()).
83///
84/// This is not exclusive: if both features are enabled, then both methods are called.
85///
86#[cfg(feature = "__rustls")]
87#[cfg_attr(docsrs, doc(cfg(feature = "rustls")))]
88#[must_use]
89pub fn rustls_default<B>() -> Client<RustlsConnector<HttpConnector>, B>
90where
91    B: HttpBody + Send,
92    B::Data: Send,
93{
94    let conn = hyper_rustls::HttpsConnectorBuilder::new();
95    #[cfg(all(
96        any(feature = "rustls-ring", feature = "rustls-aws-lc"),
97        feature = "rustls-webpki-roots"
98    ))]
99    let conn = conn.with_webpki_roots();
100    #[cfg(all(
101        any(feature = "rustls-ring", feature = "rustls-aws-lc"),
102        all(not(feature = "rustls-webpki-roots"), feature = "rustls-native-roots")
103    ))]
104    let conn = conn
105        .with_native_roots()
106        .expect("no native root CA certificates found");
107    #[cfg(all(
108        any(feature = "rustls-ring", feature = "rustls-aws-lc"),
109        any(feature = "rustls-webpki-roots", feature = "rustls-native-roots")
110    ))]
111    let conn = conn.https_only();
112    #[cfg(feature = "http1")]
113    let conn = conn.enable_http1();
114    #[cfg(feature = "rustls-http2")]
115    let conn = conn.enable_http2();
116    Builder::new(hyper_util::rt::TokioExecutor::new()).build(conn.build())
117}
118
119/// Default builder and given connector.
120pub fn with_connector_default<C, B>(conn: C) -> Client<C, B>
121where
122    C: Connect + Clone,
123    B: HttpBody + Send,
124    B::Data: Send,
125{
126    Builder::new(hyper_util::rt::TokioExecutor::new()).build(conn)
127}