async_http_client_lite/
client.rs

1use std::io;
2use std::pin::Pin;
3use std::task::{Context, Poll};
4
5use async_stream_packed::HttpClientInnerStream;
6use futures_io::{AsyncRead, AsyncWrite};
7
8//
9#[cfg(feature = "http_tunnel")]
10use async_stream_packed::HttpClientProxy;
11
12//
13use crate::client_proxy::ClientProxy;
14use crate::client_tls::ClientTls;
15
16#[cfg(feature = "http_tunnel")]
17use crate::client_http_tunnel::UnionableHttpTunnelClientGrader;
18
19#[cfg(feature = "tls")]
20use crate::client_tls::UnionableTlsClientUpgrader;
21
22//
23//
24//
25pub struct Client<S>
26where
27    S: AsyncRead + AsyncWrite + Unpin + Send + 'static,
28{
29    inner_stream: S,
30}
31
32impl<S> Client<S>
33where
34    S: AsyncRead + AsyncWrite + Unpin + Send + 'static,
35{
36    pub fn new(inner_stream: S) -> Self {
37        Self { inner_stream }
38    }
39
40    pub fn get_ref(&self) -> &S {
41        &self.inner_stream
42    }
43
44    pub fn get_mut(&mut self) -> &mut S {
45        &mut self.inner_stream
46    }
47
48    pub fn into_inner(self) -> S {
49        self.inner_stream
50    }
51}
52
53//
54//
55//
56cfg_if::cfg_if! {
57    if #[cfg(all(not(feature = "tls"), not(feature = "http_tunnel")))] {
58        pub(crate) type ClientInnerStream<S> = HttpClientInnerStream<S, (), (), ()>;
59    } else if #[cfg(all(feature = "tls", not(feature = "http_tunnel")))] {
60        pub(crate) type ClientInnerStream<S> = HttpClientInnerStream<S, (), (), UnionableTlsClientUpgrader>;
61    } else if #[cfg(all(not(feature = "tls"), feature = "http_tunnel"))] {
62        pub(crate) type ClientInnerStream<S> = HttpClientInnerStream<S, (), UnionableHttpTunnelClientGrader, ()>;
63    } else if #[cfg(all(feature = "tls", feature = "http_tunnel"))] {
64        pub(crate) type ClientInnerStream<S> = HttpClientInnerStream<S, UnionableTlsClientUpgrader, UnionableHttpTunnelClientGrader, UnionableTlsClientUpgrader>;
65    } else {
66    }
67}
68
69impl<S> Client<ClientInnerStream<S>>
70where
71    S: AsyncRead + AsyncWrite + Unpin + Send + 'static,
72{
73    cfg_if::cfg_if! {
74        if #[cfg(all(not(feature = "tls"), not(feature = "http_tunnel")))] {
75            pub async fn with(stream: S, client_proxy: Option<ClientProxy>, client_tls: Option<ClientTls>) -> io::Result<Self> {
76                if client_proxy.is_some() {
77                    debug_assert!(false, "unreachable")
78                }
79                if client_tls.is_some() {
80                    debug_assert!(false, "unreachable")
81                }
82
83                let inner_stream = HttpClientInnerStream::new(stream, None, None).await?;
84                Ok(Self::new(inner_stream))
85            }
86        } else if #[cfg(all(feature = "tls", not(feature = "http_tunnel")))] {
87            pub async fn with(stream: S, client_proxy: Option<ClientProxy>, client_tls: Option<ClientTls>) -> io::Result<Self> {
88                if client_proxy.is_some() {
89                    debug_assert!(false, "unreachable")
90                }
91
92                let tls_upgrader = client_tls.map(|x| x.into_tls_upgrader());
93                let inner_stream = HttpClientInnerStream::new(stream, None, tls_upgrader).await?;
94                Ok(Self::new(inner_stream))
95            }
96        } else if #[cfg(all(not(feature = "tls"), feature = "http_tunnel"))] {
97            pub async fn with(stream: S, client_proxy: Option<ClientProxy>, client_tls: Option<ClientTls>) -> io::Result<Self> {
98                if client_tls.is_some() {
99                    debug_assert!(false, "unreachable")
100                }
101
102                let proxy = if let Some(client_proxy) = client_proxy {
103                    match client_proxy {
104                        ClientProxy::Http(client_http_tunnel) => Some(HttpClientProxy::http(
105                            client_http_tunnel.into_http_tunnel_grader(),
106                        )),
107                        ClientProxy::Https(_, _) => unreachable!(),
108                    }
109                } else {
110                    None
111                };
112
113                let inner_stream = HttpClientInnerStream::new(stream, proxy, None).await?;
114                Ok(Self::new(inner_stream))
115            }
116        } else if #[cfg(all(feature = "tls", feature = "http_tunnel"))] {
117            pub async fn with(stream: S, client_proxy: Option<ClientProxy>, client_tls: Option<ClientTls>) -> io::Result<Self> {
118                let proxy = if let Some(client_proxy) = client_proxy {
119                    match client_proxy {
120                        ClientProxy::Http(client_http_tunnel) => Some(HttpClientProxy::http(
121                            client_http_tunnel.into_http_tunnel_grader(),
122                        )),
123                        ClientProxy::Https(proxy_client_tls, client_http_tunnel) => Some(HttpClientProxy::https(
124                            proxy_client_tls.into_tls_upgrader(),
125                            client_http_tunnel.into_http_tunnel_grader(),
126                        )),
127                    }
128                } else {
129                    None
130                };
131
132                let tls_upgrader = client_tls.map(|x| x.into_tls_upgrader());
133
134                let inner_stream = HttpClientInnerStream::new(stream, proxy, tls_upgrader).await?;
135                Ok(Self::new(inner_stream))
136            }
137        } else {
138            compile_error("unreachable")
139        }
140    }
141}
142
143//
144//
145//
146impl<S> AsyncWrite for Client<S>
147where
148    S: AsyncRead + AsyncWrite + Unpin + Send,
149{
150    fn poll_write(
151        self: Pin<&mut Self>,
152        cx: &mut Context,
153        buf: &[u8],
154    ) -> Poll<Result<usize, io::Error>> {
155        let this = self.get_mut();
156
157        Pin::new(this.get_mut()).poll_write(cx, buf)
158    }
159
160    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), io::Error>> {
161        let this = self.get_mut();
162
163        Pin::new(this.get_mut()).poll_flush(cx)
164    }
165
166    fn poll_close(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), io::Error>> {
167        let this = self.get_mut();
168
169        Pin::new(this.get_mut()).poll_close(cx)
170    }
171}
172
173impl<S> AsyncRead for Client<S>
174where
175    S: AsyncRead + AsyncWrite + Unpin + Send,
176{
177    fn poll_read(
178        self: Pin<&mut Self>,
179        cx: &mut Context,
180        buf: &mut [u8],
181    ) -> Poll<Result<usize, io::Error>> {
182        let this = self.get_mut();
183
184        Pin::new(this.get_mut()).poll_read(cx, buf)
185    }
186}