1use std::{
4 future::Future,
5 pin::Pin,
6 task::{ready, Context, Poll},
7};
8
9use bytes::Bytes;
10use http::{Request, Response};
11use http_body::Body;
12use httparse::ParserConfig;
13use tokio::io::{AsyncRead, AsyncWrite};
14
15use crate::{
16 body::Incoming,
17 dispatch::{self, TrySendError},
18 error::BoxError,
19 proto::{
20 self,
21 http1::{self, conn::Conn, role::Client, Http1Options},
22 },
23 Error, Result,
24};
25
26pub struct SendRequest<B> {
28 dispatch: dispatch::Sender<Request<B>, Response<Incoming>>,
29}
30
31#[derive(Debug)]
36#[non_exhaustive]
37pub struct Parts<T> {
38 pub io: T,
40 pub read_buf: Bytes,
49}
50
51#[must_use = "futures do nothing unless polled"]
56pub struct Connection<T, B>
57where
58 T: AsyncRead + AsyncWrite,
59 B: Body + 'static,
60{
61 inner: http1::dispatch::Dispatcher<http1::dispatch::Client<B>, B, T, Client>,
62}
63
64impl<T, B> Connection<T, B>
65where
66 T: AsyncRead + AsyncWrite + Unpin,
67 B: Body + 'static,
68 B::Error: Into<BoxError>,
69{
70 #[inline]
74 pub fn into_parts(self) -> Parts<T> {
75 let (io, read_buf, _) = self.inner.into_inner();
76 Parts { io, read_buf }
77 }
78}
79
80#[derive(Debug, Default, Clone)]
87pub struct Builder {
88 opts: Http1Options,
89}
90
91impl<B> SendRequest<B> {
94 #[inline]
98 pub fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<()>> {
99 self.dispatch.poll_ready(cx)
100 }
101
102 #[inline]
106 pub async fn ready(&mut self) -> Result<()> {
107 std::future::poll_fn(|cx| self.poll_ready(cx)).await
108 }
109
110 #[inline]
118 pub fn is_ready(&self) -> bool {
119 self.dispatch.is_ready()
120 }
121}
122
123impl<B> SendRequest<B>
124where
125 B: Body + 'static,
126{
127 pub fn try_send_request(
136 &mut self,
137 req: Request<B>,
138 ) -> impl Future<Output = Result<Response<Incoming>, TrySendError<Request<B>>>> {
139 let sent = self.dispatch.try_send(req);
140 async move {
141 match sent {
142 Ok(rx) => match rx.await {
143 Ok(res) => res,
144 Err(_) => panic!("dispatch dropped without returning error"),
146 },
147 Err(req) => {
148 debug!("connection was not ready");
149 Err(TrySendError {
150 error: Error::new_canceled().with("connection was not ready"),
151 message: Some(req),
152 })
153 }
154 }
155 }
156 }
157}
158
159impl<T, B> Connection<T, B>
162where
163 T: AsyncRead + AsyncWrite + Unpin + Send,
164 B: Body + 'static,
165 B::Error: Into<BoxError>,
166{
167 #[inline]
169 pub fn with_upgrades(self) -> upgrades::UpgradeableConnection<T, B> {
170 upgrades::UpgradeableConnection { inner: Some(self) }
171 }
172
173 pub fn poll_without_shutdown(&mut self, cx: &mut Context<'_>) -> Poll<crate::Result<()>> {
185 self.inner.poll_without_shutdown(cx)
186 }
187
188 pub async fn without_shutdown(self) -> crate::Result<Parts<T>> {
191 let mut conn = Some(self);
192 std::future::poll_fn(move |cx| -> Poll<crate::Result<Parts<T>>> {
193 ready!(conn
194 .as_mut()
195 .expect("client connection polled after completion")
196 .poll_without_shutdown(cx))?;
197 Poll::Ready(Ok(conn
198 .take()
199 .expect("client connection missing before completion")
200 .into_parts()))
201 })
202 .await
203 }
204}
205
206impl<T, B> Future for Connection<T, B>
207where
208 T: AsyncRead + AsyncWrite + Unpin,
209 B: Body + 'static,
210 B::Data: Send,
211 B::Error: Into<BoxError>,
212{
213 type Output = Result<()>;
214
215 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
216 match ready!(Pin::new(&mut self.inner).poll(cx))? {
217 proto::Dispatched::Shutdown => Poll::Ready(Ok(())),
218 proto::Dispatched::Upgrade(pending) => {
219 pending.manual();
224 Poll::Ready(Ok(()))
225 }
226 }
227 }
228}
229
230impl Builder {
233 #[inline]
235 pub fn options(mut self, opts: Http1Options) -> Self {
236 self.opts = opts;
237 self
238 }
239
240 pub async fn handshake<T, B>(self, io: T) -> Result<(SendRequest<B>, Connection<T, B>)>
245 where
246 T: AsyncRead + AsyncWrite + Unpin,
247 B: Body + 'static,
248 B::Data: Send,
249 B::Error: Into<BoxError>,
250 {
251 trace!("client handshake HTTP/1");
252
253 let (tx, rx) = dispatch::channel();
254 let mut conn = Conn::new(io);
255
256 let h1_parser_config = {
258 let mut h1_parser_config = ParserConfig::default();
259 h1_parser_config
260 .ignore_invalid_headers_in_responses(self.opts.ignore_invalid_headers_in_responses)
261 .allow_spaces_after_header_name_in_responses(
262 self.opts.allow_spaces_after_header_name_in_responses,
263 )
264 .allow_obsolete_multiline_headers_in_responses(
265 self.opts.allow_obsolete_multiline_headers_in_responses,
266 );
267 h1_parser_config
268 };
269 conn.set_h1_parser_config(h1_parser_config);
270
271 if let Some(writev) = self.opts.h1_writev {
273 if writev {
274 conn.set_write_strategy_queue();
275 } else {
276 conn.set_write_strategy_flatten();
277 }
278 }
279
280 if let Some(max_headers) = self.opts.h1_max_headers {
282 conn.set_http1_max_headers(max_headers);
283 }
284
285 if self.opts.h09_responses {
287 conn.set_h09_responses();
288 }
289
290 if let Some(sz) = self.opts.h1_read_buf_exact_size {
292 conn.set_read_buf_exact_size(sz);
293 }
294
295 if let Some(max) = self.opts.h1_max_buf_size {
297 conn.set_max_buf_size(max);
298 }
299
300 let cd = http1::dispatch::Client::new(rx);
301 let proto = http1::dispatch::Dispatcher::new(cd, conn);
302
303 Ok((SendRequest { dispatch: tx }, Connection { inner: proto }))
304 }
305}
306
307mod upgrades {
308 use super::*;
309 use crate::upgrade::Upgraded;
310
311 #[must_use = "futures do nothing unless polled"]
315 pub struct UpgradeableConnection<T, B>
316 where
317 T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
318 B: Body + 'static,
319 B::Error: Into<BoxError>,
320 {
321 pub(super) inner: Option<Connection<T, B>>,
322 }
323
324 impl<I, B> Future for UpgradeableConnection<I, B>
325 where
326 I: AsyncRead + AsyncWrite + Unpin + Send + 'static,
327 B: Body + 'static,
328 B::Data: Send,
329 B::Error: Into<BoxError>,
330 {
331 type Output = Result<()>;
332
333 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
334 match ready!(Pin::new(&mut self.inner.as_mut().unwrap().inner).poll(cx)) {
335 Ok(proto::Dispatched::Shutdown) => Poll::Ready(Ok(())),
336 Ok(proto::Dispatched::Upgrade(pending)) => {
337 let Parts { io, read_buf } = self.inner.take().unwrap().into_parts();
338 pending.fulfill(Upgraded::new(io, read_buf));
339 Poll::Ready(Ok(()))
340 }
341 Err(e) => Poll::Ready(Err(e)),
342 }
343 }
344 }
345}