@@ -13,23 +13,35 @@ use http::{Request, Response};
1313use http_body:: Body ;
1414use hyper:: {
1515 body:: Incoming ,
16- rt:: { bounds:: Http2ServerConnExec , Read , ReadBuf , Timer , Write } ,
17- server:: conn:: { http1, http2} ,
16+ rt:: { Read , ReadBuf , Timer , Write } ,
1817 service:: Service ,
1918} ;
19+
20+ #[ cfg( feature = "http1" ) ]
21+ use hyper:: server:: conn:: http1;
22+
23+ #[ cfg( feature = "http2" ) ]
24+ use hyper:: { rt:: bounds:: Http2ServerConnExec , server:: conn:: http2} ;
25+
2026use pin_project_lite:: pin_project;
2127
2228use crate :: common:: rewind:: Rewind ;
2329
24- type Result < T > = std:: result:: Result < T , Box < dyn std:: error:: Error + Send + Sync > > ;
30+ type Error = Box < dyn std:: error:: Error + Send + Sync > ;
31+
32+ type Result < T > = std:: result:: Result < T , Error > ;
2533
2634const H2_PREFACE : & [ u8 ] = b"PRI * HTTP/2.0\r \n \r \n SM\r \n \r \n " ;
2735
2836/// Http1 or Http2 connection builder.
2937#[ derive( Clone , Debug ) ]
3038pub struct Builder < E > {
39+ #[ cfg( feature = "http1" ) ]
3140 http1 : http1:: Builder ,
41+ #[ cfg( feature = "http2" ) ]
3242 http2 : http2:: Builder < E > ,
43+ #[ cfg( not( feature = "http2" ) ) ]
44+ _executor : E ,
3345}
3446
3547impl < E > Builder < E > {
@@ -50,22 +62,29 @@ impl<E> Builder<E> {
5062 /// ```
5163 pub fn new ( executor : E ) -> Self {
5264 Self {
65+ #[ cfg( feature = "http1" ) ]
5366 http1 : http1:: Builder :: new ( ) ,
67+ #[ cfg( feature = "http2" ) ]
5468 http2 : http2:: Builder :: new ( executor) ,
69+ #[ cfg( not( feature = "http2" ) ) ]
70+ _executor : executor,
5571 }
5672 }
5773
5874 /// Http1 configuration.
75+ #[ cfg( feature = "http1" ) ]
5976 pub fn http1 ( & mut self ) -> Http1Builder < ' _ , E > {
6077 Http1Builder { inner : self }
6178 }
6279
6380 /// Http2 configuration.
81+ #[ cfg( feature = "http2" ) ]
6482 pub fn http2 ( & mut self ) -> Http2Builder < ' _ , E > {
6583 Http2Builder { inner : self }
6684 }
6785
6886 /// Bind a connection together with a [`Service`].
87+ #[ cfg( feature = "http2" ) ]
6988 pub async fn serve_connection < I , S , B > ( & self , io : I , service : S ) -> Result < ( ) >
7089 where
7190 S : Service < Request < Incoming > , Response = Response < B > > ,
@@ -78,8 +97,32 @@ impl<E> Builder<E> {
7897 {
7998 let ( version, io) = read_version ( io) . await ?;
8099 match version {
100+ #[ cfg( feature = "http1" ) ]
81101 Version :: H1 => self . http1 . serve_connection ( io, service) . await ?,
82102 Version :: H2 => self . http2 . serve_connection ( io, service) . await ?,
103+ #[ cfg( any( not( feature = "http2" ) , not( feature = "http1" ) ) ) ]
104+ version => return Err ( version. unsupported ( ) ) ,
105+ }
106+
107+ Ok ( ( ) )
108+ }
109+
110+ /// Bind a connection together with a [`Service`].
111+ #[ cfg( not( feature = "http2" ) ) ]
112+ pub async fn serve_connection < I , S , B > ( & self , io : I , service : S ) -> Result < ( ) >
113+ where
114+ S : Service < Request < Incoming > , Response = Response < B > > ,
115+ S :: Future : ' static ,
116+ S :: Error : Into < Box < dyn StdError + Send + Sync > > ,
117+ B : Body + ' static ,
118+ B :: Error : Into < Box < dyn StdError + Send + Sync > > ,
119+ I : Read + Write + Unpin + ' static ,
120+ {
121+ let ( version, io) = read_version ( io) . await ?;
122+ match version {
123+ #[ cfg( feature = "http1" ) ]
124+ Version :: H1 => self . http1 . serve_connection ( io, service) . await ?,
125+ version => return Err ( version. unsupported ( ) ) ,
83126 }
84127
85128 Ok ( ( ) )
@@ -88,6 +131,7 @@ impl<E> Builder<E> {
88131 /// Bind a connection together with a [`Service`], with the ability to
89132 /// handle HTTP upgrades. This requires that the IO object implements
90133 /// `Send`.
134+ #[ cfg( feature = "http2" ) ]
91135 pub async fn serve_connection_with_upgrades < I , S , B > ( & self , io : I , service : S ) -> Result < ( ) >
92136 where
93137 S : Service < Request < Incoming > , Response = Response < B > > ,
@@ -100,13 +144,45 @@ impl<E> Builder<E> {
100144 {
101145 let ( version, io) = read_version ( io) . await ?;
102146 match version {
147+ #[ cfg( feature = "http1" ) ]
103148 Version :: H1 => {
104149 self . http1
105150 . serve_connection ( io, service)
106151 . with_upgrades ( )
107152 . await ?
108153 }
109154 Version :: H2 => self . http2 . serve_connection ( io, service) . await ?,
155+ #[ cfg( any( not( feature = "http2" ) , not( feature = "http1" ) ) ) ]
156+ version => return Err ( version. unsupported ( ) ) ,
157+ }
158+
159+ Ok ( ( ) )
160+ }
161+
162+ /// Bind a connection together with a [`Service`], with the ability to
163+ /// handle HTTP upgrades. This requires that the IO object implements
164+ /// `Send`.
165+ #[ cfg( not( feature = "http2" ) ) ]
166+ pub async fn serve_connection_with_upgrades < I , S , B > ( & self , io : I , service : S ) -> Result < ( ) >
167+ where
168+ S : Service < Request < Incoming > , Response = Response < B > > ,
169+ S :: Future : ' static ,
170+ S :: Error : Into < Box < dyn StdError + Send + Sync > > ,
171+ B : Body + ' static ,
172+ B :: Error : Into < Box < dyn StdError + Send + Sync > > ,
173+ I : Read + Write + Unpin + Send + ' static ,
174+ {
175+ let ( version, io) = read_version ( io) . await ?;
176+ match version {
177+ #[ cfg( feature = "http1" ) ]
178+ Version :: H1 => {
179+ self . http1
180+ . serve_connection ( io, service)
181+ . with_upgrades ( )
182+ . await ?
183+ }
184+ #[ cfg( any( not( feature = "http2" ) , not( feature = "http1" ) ) ) ]
185+ version => return Err ( version. unsupported ( ) ) ,
110186 }
111187
112188 Ok ( ( ) )
@@ -117,6 +193,18 @@ enum Version {
117193 H1 ,
118194 H2 ,
119195}
196+
197+ impl Version {
198+ #[ must_use]
199+ #[ cfg( any( not( feature = "http2" ) , not( feature = "http1" ) ) ) ]
200+ pub fn unsupported ( self ) -> Error {
201+ match self {
202+ Version :: H1 => Error :: from ( "HTTP/1 is not supported" ) ,
203+ Version :: H2 => Error :: from ( "HTTP/2 is not supported" ) ,
204+ }
205+ }
206+ }
207+
120208async fn read_version < ' a , A > ( mut reader : A ) -> IoResult < ( Version , Rewind < A > ) >
121209where
122210 A : Read + Unpin ,
@@ -172,12 +260,15 @@ where
172260}
173261
174262/// Http1 part of builder.
263+ #[ cfg( feature = "http1" ) ]
175264pub struct Http1Builder < ' a , E > {
176265 inner : & ' a mut Builder < E > ,
177266}
178267
268+ #[ cfg( feature = "http1" ) ]
179269impl < E > Http1Builder < ' _ , E > {
180270 /// Http2 configuration.
271+ #[ cfg( feature = "http2" ) ]
181272 pub fn http2 ( & mut self ) -> Http2Builder < ' _ , E > {
182273 Http2Builder {
183274 inner : & mut self . inner ,
@@ -292,6 +383,7 @@ impl<E> Http1Builder<'_, E> {
292383 }
293384
294385 /// Bind a connection together with a [`Service`].
386+ #[ cfg( feature = "http2" ) ]
295387 pub async fn serve_connection < I , S , B > ( & self , io : I , service : S ) -> Result < ( ) >
296388 where
297389 S : Service < Request < Incoming > , Response = Response < B > > ,
@@ -304,14 +396,31 @@ impl<E> Http1Builder<'_, E> {
304396 {
305397 self . inner . serve_connection ( io, service) . await
306398 }
399+
400+ /// Bind a connection together with a [`Service`].
401+ #[ cfg( not( feature = "http2" ) ) ]
402+ pub async fn serve_connection < I , S , B > ( & self , io : I , service : S ) -> Result < ( ) >
403+ where
404+ S : Service < Request < Incoming > , Response = Response < B > > ,
405+ S :: Future : ' static ,
406+ S :: Error : Into < Box < dyn StdError + Send + Sync > > ,
407+ B : Body + ' static ,
408+ B :: Error : Into < Box < dyn StdError + Send + Sync > > ,
409+ I : Read + Write + Unpin + ' static ,
410+ {
411+ self . inner . serve_connection ( io, service) . await
412+ }
307413}
308414
309415/// Http2 part of builder.
416+ #[ cfg( feature = "http2" ) ]
310417pub struct Http2Builder < ' a , E > {
311418 inner : & ' a mut Builder < E > ,
312419}
313420
421+ #[ cfg( feature = "http2" ) ]
314422impl < E > Http2Builder < ' _ , E > {
423+ #[ cfg( feature = "http1" ) ]
315424 /// Http1 configuration.
316425 pub fn http1 ( & mut self ) -> Http1Builder < ' _ , E > {
317426 Http1Builder {
0 commit comments