@@ -13,23 +13,38 @@ 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:: {
25+ rt:: bounds:: Http2ServerConnExec ,
26+ server:: conn:: http2,
27+ } ;
28+
2029use pin_project_lite:: pin_project;
2130
2231use crate :: common:: rewind:: Rewind ;
2332
24- type Result < T > = std:: result:: Result < T , Box < dyn std:: error:: Error + Send + Sync > > ;
33+ type Error = Box < dyn std:: error:: Error + Send + Sync > ;
34+
35+ type Result < T > = std:: result:: Result < T , Error > ;
2536
2637const H2_PREFACE : & [ u8 ] = b"PRI * HTTP/2.0\r \n \r \n SM\r \n \r \n " ;
2738
2839/// Http1 or Http2 connection builder.
2940#[ derive( Clone , Debug ) ]
3041pub struct Builder < E > {
42+ #[ cfg( feature = "http1" ) ]
3143 http1 : http1:: Builder ,
44+ #[ cfg( feature = "http2" ) ]
3245 http2 : http2:: Builder < E > ,
46+ #[ cfg( not( feature = "http2" ) ) ]
47+ _executor : E ,
3348}
3449
3550impl < E > Builder < E > {
@@ -50,22 +65,29 @@ impl<E> Builder<E> {
5065 /// ```
5166 pub fn new ( executor : E ) -> Self {
5267 Self {
68+ #[ cfg( feature = "http1" ) ]
5369 http1 : http1:: Builder :: new ( ) ,
70+ #[ cfg( feature = "http2" ) ]
5471 http2 : http2:: Builder :: new ( executor) ,
72+ #[ cfg( not( feature = "http2" ) ) ]
73+ _executor : executor,
5574 }
5675 }
5776
5877 /// Http1 configuration.
78+ #[ cfg( feature = "http1" ) ]
5979 pub fn http1 ( & mut self ) -> Http1Builder < ' _ , E > {
6080 Http1Builder { inner : self }
6181 }
6282
6383 /// Http2 configuration.
84+ #[ cfg( feature = "http2" ) ]
6485 pub fn http2 ( & mut self ) -> Http2Builder < ' _ , E > {
6586 Http2Builder { inner : self }
6687 }
6788
6889 /// Bind a connection together with a [`Service`].
90+ #[ cfg( feature = "http2" ) ]
6991 pub async fn serve_connection < I , S , B > ( & self , io : I , service : S ) -> Result < ( ) >
7092 where
7193 S : Service < Request < Incoming > , Response = Response < B > > ,
@@ -78,8 +100,32 @@ impl<E> Builder<E> {
78100 {
79101 let ( version, io) = read_version ( io) . await ?;
80102 match version {
103+ #[ cfg( feature = "http1" ) ]
81104 Version :: H1 => self . http1 . serve_connection ( io, service) . await ?,
82105 Version :: H2 => self . http2 . serve_connection ( io, service) . await ?,
106+ #[ cfg( any( not( feature = "http2" ) , not( feature = "http1" ) ) ) ]
107+ version => return Err ( version. unsupported ( ) ) ,
108+ }
109+
110+ Ok ( ( ) )
111+ }
112+
113+ /// Bind a connection together with a [`Service`].
114+ #[ cfg( not( feature = "http2" ) ) ]
115+ pub async fn serve_connection < I , S , B > ( & self , io : I , service : S ) -> Result < ( ) >
116+ where
117+ S : Service < Request < Incoming > , Response = Response < B > > ,
118+ S :: Future : ' static ,
119+ S :: Error : Into < Box < dyn StdError + Send + Sync > > ,
120+ B : Body + ' static ,
121+ B :: Error : Into < Box < dyn StdError + Send + Sync > > ,
122+ I : Read + Write + Unpin + ' static ,
123+ {
124+ let ( version, io) = read_version ( io) . await ?;
125+ match version {
126+ #[ cfg( feature = "http1" ) ]
127+ Version :: H1 => self . http1 . serve_connection ( io, service) . await ?,
128+ version => return Err ( version. unsupported ( ) ) ,
83129 }
84130
85131 Ok ( ( ) )
@@ -88,6 +134,7 @@ impl<E> Builder<E> {
88134 /// Bind a connection together with a [`Service`], with the ability to
89135 /// handle HTTP upgrades. This requires that the IO object implements
90136 /// `Send`.
137+ #[ cfg( feature = "http2" ) ]
91138 pub async fn serve_connection_with_upgrades < I , S , B > ( & self , io : I , service : S ) -> Result < ( ) >
92139 where
93140 S : Service < Request < Incoming > , Response = Response < B > > ,
@@ -100,13 +147,45 @@ impl<E> Builder<E> {
100147 {
101148 let ( version, io) = read_version ( io) . await ?;
102149 match version {
150+ #[ cfg( feature = "http1" ) ]
103151 Version :: H1 => {
104152 self . http1
105153 . serve_connection ( io, service)
106154 . with_upgrades ( )
107155 . await ?
108156 }
109157 Version :: H2 => self . http2 . serve_connection ( io, service) . await ?,
158+ #[ cfg( any( not( feature = "http2" ) , not( feature = "http1" ) ) ) ]
159+ version => return Err ( version. unsupported ( ) ) ,
160+ }
161+
162+ Ok ( ( ) )
163+ }
164+
165+ /// Bind a connection together with a [`Service`], with the ability to
166+ /// handle HTTP upgrades. This requires that the IO object implements
167+ /// `Send`.
168+ #[ cfg( not( feature = "http2" ) ) ]
169+ pub async fn serve_connection_with_upgrades < I , S , B > ( & self , io : I , service : S ) -> Result < ( ) >
170+ where
171+ S : Service < Request < Incoming > , Response = Response < B > > ,
172+ S :: Future : ' static ,
173+ S :: Error : Into < Box < dyn StdError + Send + Sync > > ,
174+ B : Body + ' static ,
175+ B :: Error : Into < Box < dyn StdError + Send + Sync > > ,
176+ I : Read + Write + Unpin + Send + ' static ,
177+ {
178+ let ( version, io) = read_version ( io) . await ?;
179+ match version {
180+ #[ cfg( feature = "http1" ) ]
181+ Version :: H1 => {
182+ self . http1
183+ . serve_connection ( io, service)
184+ . with_upgrades ( )
185+ . await ?
186+ }
187+ #[ cfg( any( not( feature = "http2" ) , not( feature = "http1" ) ) ) ]
188+ version => return Err ( version. unsupported ( ) ) ,
110189 }
111190
112191 Ok ( ( ) )
@@ -117,6 +196,18 @@ enum Version {
117196 H1 ,
118197 H2 ,
119198}
199+
200+ impl Version {
201+ #[ must_use]
202+ #[ cfg( any( not( feature = "http2" ) , not( feature = "http1" ) ) ) ]
203+ pub fn unsupported ( self ) -> Error {
204+ match self {
205+ Version :: H1 => Error :: from ( "HTTP/1 is not supported" ) ,
206+ Version :: H2 => Error :: from ( "HTTP/2 is not supported" ) ,
207+ }
208+ }
209+ }
210+
120211async fn read_version < ' a , A > ( mut reader : A ) -> IoResult < ( Version , Rewind < A > ) >
121212where
122213 A : Read + Unpin ,
@@ -172,12 +263,15 @@ where
172263}
173264
174265/// Http1 part of builder.
266+ #[ cfg( feature = "http1" ) ]
175267pub struct Http1Builder < ' a , E > {
176268 inner : & ' a mut Builder < E > ,
177269}
178270
271+ #[ cfg( feature = "http1" ) ]
179272impl < E > Http1Builder < ' _ , E > {
180273 /// Http2 configuration.
274+ #[ cfg( feature = "http2" ) ]
181275 pub fn http2 ( & mut self ) -> Http2Builder < ' _ , E > {
182276 Http2Builder {
183277 inner : & mut self . inner ,
@@ -292,6 +386,7 @@ impl<E> Http1Builder<'_, E> {
292386 }
293387
294388 /// Bind a connection together with a [`Service`].
389+ #[ cfg( feature = "http2" ) ]
295390 pub async fn serve_connection < I , S , B > ( & self , io : I , service : S ) -> Result < ( ) >
296391 where
297392 S : Service < Request < Incoming > , Response = Response < B > > ,
@@ -304,14 +399,31 @@ impl<E> Http1Builder<'_, E> {
304399 {
305400 self . inner . serve_connection ( io, service) . await
306401 }
402+
403+ /// Bind a connection together with a [`Service`].
404+ #[ cfg( not( feature = "http2" ) ) ]
405+ pub async fn serve_connection < I , S , B > ( & self , io : I , service : S ) -> Result < ( ) >
406+ where
407+ S : Service < Request < Incoming > , Response = Response < B > > ,
408+ S :: Future : ' static ,
409+ S :: Error : Into < Box < dyn StdError + Send + Sync > > ,
410+ B : Body + ' static ,
411+ B :: Error : Into < Box < dyn StdError + Send + Sync > > ,
412+ I : Read + Write + Unpin + ' static ,
413+ {
414+ self . inner . serve_connection ( io, service) . await
415+ }
307416}
308417
309418/// Http2 part of builder.
419+ #[ cfg( feature = "http2" ) ]
310420pub struct Http2Builder < ' a , E > {
311421 inner : & ' a mut Builder < E > ,
312422}
313423
424+ #[ cfg( feature = "http2" ) ]
314425impl < E > Http2Builder < ' _ , E > {
426+ #[ cfg( feature = "http1" ) ]
315427 /// Http1 configuration.
316428 pub fn http1 ( & mut self ) -> Http1Builder < ' _ , E > {
317429 Http1Builder {
0 commit comments