async_http_client_lite/
client.rs1use std::io;
2use std::pin::Pin;
3use std::task::{Context, Poll};
4
5use async_stream_packed::HttpClientInnerStream;
6use futures_io::{AsyncRead, AsyncWrite};
7
8#[cfg(feature = "http_tunnel")]
10use async_stream_packed::HttpClientProxy;
11
12use 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
22pub 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
53cfg_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
143impl<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}