Skip to main content

aioduct/client/
engine_local.rs

1use http::{Method, Uri};
2
3use super::HttpEngineLocal;
4use super::builder::HttpEngineBuilder;
5use super::resolve_request_url;
6use crate::error::Error;
7use crate::runtime::{ConnectorLocal, RuntimeLocal};
8
9impl<R: RuntimeLocal, C: ConnectorLocal + Clone + Default> HttpEngineLocal<R, C> {
10    /// Create a new client with default settings for a completion-based runtime.
11    pub fn new() -> Self {
12        Self::with_connector(C::default())
13    }
14
15    /// Create a new [`HttpEngineBuilder`] for a completion-based runtime.
16    pub fn builder() -> HttpEngineBuilder<R, C> {
17        Self::builder_with_connector(C::default())
18    }
19
20    #[cfg(feature = "rustls")]
21    /// Create a client with rustls TLS for a completion-based runtime.
22    pub fn with_rustls() -> Self {
23        Self::with_rustls_connector(C::default())
24    }
25}
26
27impl<R: RuntimeLocal, C: ConnectorLocal + Clone + Default> Default for HttpEngineLocal<R, C> {
28    fn default() -> Self {
29        Self::new()
30    }
31}
32
33impl<R: RuntimeLocal, C: ConnectorLocal + Clone> HttpEngineLocal<R, C> {
34    /// Create a new [`HttpEngineBuilder`] with a specific connector for a completion-based runtime.
35    pub fn builder_with_connector(connector: C) -> HttpEngineBuilder<R, C> {
36        HttpEngineBuilder::new(connector)
37    }
38
39    /// Resolve a request input URL against the configured base URL, if any.
40    fn resolve_url(&self, uri: &str) -> Result<(Uri, Option<String>), Error> {
41        resolve_request_url(self.core.base_url.as_deref(), uri)
42    }
43
44    /// Create a new client with default settings and a specific connector.
45    #[allow(clippy::expect_used)]
46    pub fn with_connector(connector: C) -> Self {
47        Self::builder_with_connector(connector)
48            .build_local()
49            .expect("default build_local")
50    }
51
52    #[cfg(feature = "rustls")]
53    #[allow(clippy::expect_used)]
54    /// Create a client with rustls TLS and a specific connector for a completion-based runtime.
55    pub fn with_rustls_connector(connector: C) -> Self {
56        Self::builder_with_connector(connector)
57            .tls(crate::tls::RustlsConnector::with_webpki_roots())
58            .build_local()
59            .expect("rustls build_local")
60    }
61
62    /// Start a GET request to the given URL.
63    pub fn get_local(
64        &self,
65        uri: &str,
66    ) -> Result<crate::request::RequestBuilderLocal<'_, R, C>, Error> {
67        let (uri, fragment) = self.resolve_url(uri)?;
68        Ok(crate::request::RequestBuilderLocal::new(
69            self,
70            Method::GET,
71            uri,
72            fragment,
73        ))
74    }
75
76    /// Start a POST request to the given URL.
77    pub fn post_local(
78        &self,
79        uri: &str,
80    ) -> Result<crate::request::RequestBuilderLocal<'_, R, C>, Error> {
81        let (uri, fragment) = self.resolve_url(uri)?;
82        Ok(crate::request::RequestBuilderLocal::new(
83            self,
84            Method::POST,
85            uri,
86            fragment,
87        ))
88    }
89
90    /// Start a request with the given method and URL.
91    pub fn request_local(
92        &self,
93        method: Method,
94        uri: &str,
95    ) -> Result<crate::request::RequestBuilderLocal<'_, R, C>, Error> {
96        let (uri, fragment) = self.resolve_url(uri)?;
97        Ok(crate::request::RequestBuilderLocal::new(
98            self, method, uri, fragment,
99        ))
100    }
101
102    /// Start a parallel chunk download for the given URL.
103    pub fn chunk_download_local(
104        &self,
105        url: &str,
106    ) -> crate::chunk_download::ChunkDownloadLocal<R, C> {
107        crate::chunk_download::ChunkDownloadLocal::new(self.clone(), url.to_owned())
108    }
109
110    /// Resolve a hostname to all socket addresses using the configured DNS resolver.
111    ///
112    /// Returns every address the resolver provides. This enables service discovery
113    /// and custom load-balancing: resolve once, select an address with your
114    /// strategy (round-robin, least-connections, consistent hashing), then send the
115    /// request to the chosen address via
116    /// [`crate::RequestBuilderLocal::force_addr`].
117    ///
118    /// For a host that is already an IP literal, this returns a single-element vec
119    /// without consulting any resolver.
120    pub async fn resolve_all(
121        &self,
122        host: &str,
123        port: u16,
124    ) -> Result<Vec<std::net::SocketAddr>, Error> {
125        self.core.resolve_all_authority_raw(host, port).await
126    }
127
128    /// Forward an incoming HTTP request to an upstream server.
129    pub fn forward_local<B>(
130        &self,
131        request: http::Request<B>,
132    ) -> crate::forward::forward_local::ForwardBuilderLocal<'_, R, C, B>
133    where
134        B: http_body::Body<Data = bytes::Bytes> + 'static,
135        B::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
136    {
137        crate::forward::forward_local::ForwardBuilderLocal::new(self, request)
138    }
139}