@@ -4,6 +4,7 @@ use std::error::Error as StdError;
44use std:: fmt;
55use std:: sync:: Arc ;
66
7+ use bytes:: Bytes ;
78use http:: { Request , Response } ;
89use httparse:: ParserConfig ;
910use tokio:: io:: { AsyncRead , AsyncWrite } ;
@@ -27,6 +28,27 @@ pub struct SendRequest<B> {
2728 dispatch : dispatch:: Sender < Request < B > , Response < Recv > > ,
2829}
2930
31+ /// Deconstructed parts of a `Connection`.
32+ ///
33+ /// This allows taking apart a `Connection` at a later time, in order to
34+ /// reclaim the IO object, and additional related pieces.
35+ #[ derive( Debug ) ]
36+ pub struct Parts < T > {
37+ /// The original IO object used in the handshake.
38+ pub io : T ,
39+ /// A buffer of bytes that have been read but not processed as HTTP.
40+ ///
41+ /// For instance, if the `Connection` is used for an HTTP upgrade request,
42+ /// it is possible the server sent back the first bytes of the new protocol
43+ /// along with the response upgrade.
44+ ///
45+ /// You will want to check for any existing bytes if you plan to continue
46+ /// communicating on the IO object.
47+ pub read_buf : Bytes ,
48+ _inner : ( ) ,
49+ }
50+
51+
3052/// A future that processes all HTTP state for the IO object.
3153///
3254/// In most cases, this should just be spawned into an executor, so that it
4062 inner : Option < Dispatcher < T , B > > ,
4163}
4264
65+ impl < T , B > Connection < T , B >
66+ where
67+ T : AsyncRead + AsyncWrite + Send + Unpin + ' static ,
68+ B : Body + ' static ,
69+ B :: Error : Into < Box < dyn StdError + Send + Sync > > ,
70+ {
71+ /// Return the inner IO object, and additional information.
72+ ///
73+ /// Only works for HTTP/1 connections. HTTP/2 connections will panic.
74+ pub fn into_parts ( self ) -> Parts < T > {
75+ let ( io, read_buf, _) = self . inner . expect ( "already upgraded" ) . into_inner ( ) ;
76+ Parts {
77+ io,
78+ read_buf,
79+ _inner : ( ) ,
80+ }
81+ }
82+
83+ /// Poll the connection for completion, but without calling `shutdown`
84+ /// on the underlying IO.
85+ ///
86+ /// This is useful to allow running a connection while doing an HTTP
87+ /// upgrade. Once the upgrade is completed, the connection would be "done",
88+ /// but it is not desired to actually shutdown the IO object. Instead you
89+ /// would take it back using `into_parts`.
90+ ///
91+ /// Use [`poll_fn`](https://docs.rs/futures/0.1.25/futures/future/fn.poll_fn.html)
92+ /// and [`try_ready!`](https://docs.rs/futures/0.1.25/futures/macro.try_ready.html)
93+ /// to work with this function; or use the `without_shutdown` wrapper.
94+ pub fn poll_without_shutdown ( & mut self , cx : & mut task:: Context < ' _ > ) -> Poll < crate :: Result < ( ) > > {
95+ self . inner . as_mut ( ) . expect ( "algready upgraded" ) . poll_without_shutdown ( cx)
96+ }
97+ }
98+
4399/// A builder to configure an HTTP connection.
44100///
45101/// After setting options, the builder is used to create a handshake future.
@@ -52,6 +108,8 @@ pub struct Builder {
52108 h1_title_case_headers : bool ,
53109 h1_preserve_header_case : bool ,
54110 #[ cfg( feature = "ffi" ) ]
111+ h1_headers_raw : bool ,
112+ #[ cfg( feature = "ffi" ) ]
55113 h1_preserve_header_order : bool ,
56114 h1_read_buf_exact_size : Option < usize > ,
57115 h1_max_buf_size : Option < usize > ,
@@ -61,11 +119,14 @@ pub struct Builder {
61119///
62120/// This is a shortcut for `Builder::new().handshake(io)`.
63121/// See [`client::conn`](crate::client::conn) for more.
64- pub async fn handshake < T > (
122+ pub async fn handshake < T , B > (
65123 io : T ,
66- ) -> crate :: Result < ( SendRequest < crate :: Recv > , Connection < T , crate :: Recv > ) >
124+ ) -> crate :: Result < ( SendRequest < B > , Connection < T , B > ) >
67125where
68126 T : AsyncRead + AsyncWrite + Unpin + Send + ' static ,
127+ B : Body + ' static ,
128+ B :: Data : Send ,
129+ B :: Error : Into < Box < dyn StdError + Send + Sync > > ,
69130{
70131 Builder :: new ( ) . handshake ( io) . await
71132}
@@ -80,6 +141,13 @@ impl<B> SendRequest<B> {
80141 self . dispatch . poll_ready ( cx)
81142 }
82143
144+ /// Waits until the dispatcher is ready
145+ ///
146+ /// If the associated connection is closed, this returns an Error.
147+ pub async fn ready ( & mut self ) -> crate :: Result < ( ) > {
148+ futures_util:: future:: poll_fn ( |cx| self . poll_ready ( cx) ) . await
149+ }
150+
83151 /*
84152 pub(super) async fn when_ready(self) -> crate::Result<Self> {
85153 let mut me = Some(self);
@@ -232,6 +300,8 @@ impl Builder {
232300 h1_title_case_headers : false ,
233301 h1_preserve_header_case : false ,
234302 #[ cfg( feature = "ffi" ) ]
303+ h1_headers_raw : false ,
304+ #[ cfg( feature = "ffi" ) ]
235305 h1_preserve_header_order : false ,
236306 h1_max_buf_size : None ,
237307 }
@@ -386,6 +456,12 @@ impl Builder {
386456 self
387457 }
388458
459+ #[ cfg( feature = "ffi" ) ]
460+ pub ( crate ) fn http1_headers_raw ( & mut self , enabled : bool ) -> & mut Builder {
461+ self . h1_headers_raw = enabled;
462+ self
463+ }
464+
389465 /// Sets the exact size of the read buffer to *always* use.
390466 ///
391467 /// Note that setting this option unsets the `http1_max_buf_size` option.
@@ -459,6 +535,10 @@ impl Builder {
459535 if opts. h1_preserve_header_order {
460536 conn. set_preserve_header_order ( ) ;
461537 }
538+ #[ cfg( feature = "ffi" ) ]
539+ if opts. h1_headers_raw {
540+ conn. set_raw_headers ( true ) ;
541+ }
462542 if opts. h09_responses {
463543 conn. set_h09_responses ( ) ;
464544 }
0 commit comments