@@ -15,23 +15,52 @@ use http::{Request, Response};
1515use http_body:: Body ;
1616use hyper:: {
1717 body:: Incoming ,
18- rt:: { bounds:: Http2ServerConnExec , Read , ReadBuf , Timer , Write } ,
19- server:: conn:: { http1, http2} ,
18+ rt:: { Read , ReadBuf , Timer , Write } ,
2019 service:: Service ,
2120} ;
21+
22+ #[ cfg( feature = "http1" ) ]
23+ use hyper:: server:: conn:: http1;
24+
25+ #[ cfg( feature = "http2" ) ]
26+ use hyper:: { rt:: bounds:: Http2ServerConnExec , server:: conn:: http2} ;
27+
28+ #[ cfg( any( not( feature = "http2" ) , not( feature = "http1" ) ) ) ]
29+ use std:: marker:: PhantomData ;
30+
2231use pin_project_lite:: pin_project;
2332
2433use crate :: common:: rewind:: Rewind ;
2534
26- type Result < T > = std:: result:: Result < T , Box < dyn std:: error:: Error + Send + Sync > > ;
35+ type Error = Box < dyn std:: error:: Error + Send + Sync > ;
36+
37+ type Result < T > = std:: result:: Result < T , Error > ;
2738
2839const H2_PREFACE : & [ u8 ] = b"PRI * HTTP/2.0\r \n \r \n SM\r \n \r \n " ;
2940
41+ /// Exactly equivalent to [`Http2ServerConnExec`].
42+ #[ cfg( feature = "http2" ) ]
43+ pub trait HttpServerConnExec < A , B : Body > : Http2ServerConnExec < A , B > { }
44+
45+ #[ cfg( feature = "http2" ) ]
46+ impl < A , B : Body , T : Http2ServerConnExec < A , B > > HttpServerConnExec < A , B > for T { }
47+
48+ /// Exactly equivalent to [`Http2ServerConnExec`].
49+ #[ cfg( not( feature = "http2" ) ) ]
50+ pub trait HttpServerConnExec < A , B : Body > { }
51+
52+ #[ cfg( not( feature = "http2" ) ) ]
53+ impl < A , B : Body , T > HttpServerConnExec < A , B > for T { }
54+
3055/// Http1 or Http2 connection builder.
3156#[ derive( Clone , Debug ) ]
3257pub struct Builder < E > {
58+ #[ cfg( feature = "http1" ) ]
3359 http1 : http1:: Builder ,
60+ #[ cfg( feature = "http2" ) ]
3461 http2 : http2:: Builder < E > ,
62+ #[ cfg( not( feature = "http2" ) ) ]
63+ _executor : E ,
3564}
3665
3766impl < E > Builder < E > {
@@ -52,17 +81,23 @@ impl<E> Builder<E> {
5281 /// ```
5382 pub fn new ( executor : E ) -> Self {
5483 Self {
84+ #[ cfg( feature = "http1" ) ]
5585 http1 : http1:: Builder :: new ( ) ,
86+ #[ cfg( feature = "http2" ) ]
5687 http2 : http2:: Builder :: new ( executor) ,
88+ #[ cfg( not( feature = "http2" ) ) ]
89+ _executor : executor,
5790 }
5891 }
5992
6093 /// Http1 configuration.
94+ #[ cfg( feature = "http1" ) ]
6195 pub fn http1 ( & mut self ) -> Http1Builder < ' _ , E > {
6296 Http1Builder { inner : self }
6397 }
6498
6599 /// Http2 configuration.
100+ #[ cfg( feature = "http2" ) ]
66101 pub fn http2 ( & mut self ) -> Http2Builder < ' _ , E > {
67102 Http2Builder { inner : self }
68103 }
@@ -76,7 +111,7 @@ impl<E> Builder<E> {
76111 B : Body + ' static ,
77112 B :: Error : Into < Box < dyn StdError + Send + Sync > > ,
78113 I : Read + Write + Unpin + ' static ,
79- E : Http2ServerConnExec < S :: Future , B > ,
114+ E : HttpServerConnExec < S :: Future , B > ,
80115 {
81116 Connection {
82117 state : ConnState :: ReadVersion {
@@ -102,7 +137,7 @@ impl<E> Builder<E> {
102137 B : Body + ' static ,
103138 B :: Error : Into < Box < dyn StdError + Send + Sync > > ,
104139 I : Read + Write + Unpin + Send + ' static ,
105- E : Http2ServerConnExec < S :: Future , B > ,
140+ E : HttpServerConnExec < S :: Future , B > ,
106141 {
107142 UpgradeableConnection {
108143 state : UpgradeableConnState :: ReadVersion {
@@ -113,12 +148,24 @@ impl<E> Builder<E> {
113148 }
114149 }
115150}
151+
116152#[ derive( Copy , Clone ) ]
117153enum Version {
118154 H1 ,
119155 H2 ,
120156}
121157
158+ impl Version {
159+ #[ must_use]
160+ #[ cfg( any( not( feature = "http2" ) , not( feature = "http1" ) ) ) ]
161+ pub fn unsupported ( self ) -> Error {
162+ match self {
163+ Version :: H1 => Error :: from ( "HTTP/1 is not supported" ) ,
164+ Version :: H2 => Error :: from ( "HTTP/2 is not supported" ) ,
165+ }
166+ }
167+ }
168+
122169fn read_version < I > ( io : I ) -> ReadVersion < I >
123170where
124171 I : Read + Unpin ,
@@ -202,6 +249,18 @@ pin_project! {
202249 }
203250}
204251
252+ #[ cfg( feature = "http1" ) ]
253+ type Http1Connection < I , S > = hyper:: server:: conn:: http1:: Connection < Rewind < I > , S > ;
254+
255+ #[ cfg( not( feature = "http1" ) ) ]
256+ type Http1Connection < I , S > = ( PhantomData < I > , PhantomData < S > ) ;
257+
258+ #[ cfg( feature = "http2" ) ]
259+ type Http2Connection < I , S , E > = hyper:: server:: conn:: http2:: Connection < Rewind < I > , S , E > ;
260+
261+ #[ cfg( not( feature = "http2" ) ) ]
262+ type Http2Connection < I , S , E > = ( PhantomData < I > , PhantomData < S > , PhantomData < E > ) ;
263+
205264pin_project ! {
206265 #[ project = ConnStateProj ]
207266 enum ConnState <' a, I , S , E >
@@ -216,11 +275,11 @@ pin_project! {
216275 } ,
217276 H1 {
218277 #[ pin]
219- conn: hyper :: server :: conn :: http1 :: Connection < Rewind < I > , S >,
278+ conn: Http1Connection < I , S >,
220279 } ,
221280 H2 {
222281 #[ pin]
223- conn: hyper :: server :: conn :: http2 :: Connection < Rewind < I > , S , E >,
282+ conn: Http2Connection < I , S , E >,
224283 } ,
225284 }
226285}
@@ -232,7 +291,7 @@ where
232291 I : Read + Write + Unpin ,
233292 B : Body + ' static ,
234293 B :: Error : Into < Box < dyn StdError + Send + Sync > > ,
235- E : Http2ServerConnExec < S :: Future , B > ,
294+ E : HttpServerConnExec < S :: Future , B > ,
236295{
237296 /// Start a graceful shutdown process for this connection.
238297 ///
@@ -245,8 +304,12 @@ where
245304 pub fn graceful_shutdown ( self : Pin < & mut Self > ) {
246305 match self . project ( ) . state . project ( ) {
247306 ConnStateProj :: ReadVersion { .. } => { }
307+ #[ cfg( feature = "http1" ) ]
248308 ConnStateProj :: H1 { conn } => conn. graceful_shutdown ( ) ,
309+ #[ cfg( feature = "http2" ) ]
249310 ConnStateProj :: H2 { conn } => conn. graceful_shutdown ( ) ,
311+ #[ cfg( any( not( feature = "http1" ) , not( feature = "http2" ) ) ) ]
312+ _ => unreachable ! ( ) ,
250313 }
251314 }
252315}
@@ -259,7 +322,7 @@ where
259322 B : Body + ' static ,
260323 B :: Error : Into < Box < dyn StdError + Send + Sync > > ,
261324 I : Read + Write + Unpin + ' static ,
262- E : Http2ServerConnExec < S :: Future , B > ,
325+ E : HttpServerConnExec < S :: Future , B > ,
263326{
264327 type Output = Result < ( ) > ;
265328
@@ -276,22 +339,30 @@ where
276339 let ( version, io) = ready ! ( read_version. poll( cx) ) ?;
277340 let service = service. take ( ) . unwrap ( ) ;
278341 match version {
342+ #[ cfg( feature = "http1" ) ]
279343 Version :: H1 => {
280344 let conn = builder. http1 . serve_connection ( io, service) ;
281345 this. state . set ( ConnState :: H1 { conn } ) ;
282346 }
347+ #[ cfg( feature = "http2" ) ]
283348 Version :: H2 => {
284349 let conn = builder. http2 . serve_connection ( io, service) ;
285350 this. state . set ( ConnState :: H2 { conn } ) ;
286351 }
352+ #[ cfg( any( not( feature = "http1" ) , not( feature = "http2" ) ) ) ]
353+ _ => return Poll :: Ready ( Err ( version. unsupported ( ) ) ) ,
287354 }
288355 }
356+ #[ cfg( feature = "http1" ) ]
289357 ConnStateProj :: H1 { conn } => {
290358 return conn. poll ( cx) . map_err ( Into :: into) ;
291359 }
360+ #[ cfg( feature = "http2" ) ]
292361 ConnStateProj :: H2 { conn } => {
293362 return conn. poll ( cx) . map_err ( Into :: into) ;
294363 }
364+ #[ cfg( any( not( feature = "http1" ) , not( feature = "http2" ) ) ) ]
365+ _ => unreachable ! ( ) ,
295366 }
296367 }
297368 }
@@ -308,6 +379,12 @@ pin_project! {
308379 }
309380}
310381
382+ #[ cfg( feature = "http1" ) ]
383+ type Http1UpgradeableConnection < I , S > = hyper:: server:: conn:: http1:: UpgradeableConnection < I , S > ;
384+
385+ #[ cfg( not( feature = "http1" ) ) ]
386+ type Http1UpgradeableConnection < I , S > = ( PhantomData < I > , PhantomData < S > ) ;
387+
311388pin_project ! {
312389 #[ project = UpgradeableConnStateProj ]
313390 enum UpgradeableConnState <' a, I , S , E >
@@ -322,11 +399,11 @@ pin_project! {
322399 } ,
323400 H1 {
324401 #[ pin]
325- conn: hyper :: server :: conn :: http1 :: UpgradeableConnection <Rewind <I >, S >,
402+ conn: Http1UpgradeableConnection <Rewind <I >, S >,
326403 } ,
327404 H2 {
328405 #[ pin]
329- conn: hyper :: server :: conn :: http2 :: Connection < Rewind < I > , S , E >,
406+ conn: Http2Connection < I , S , E >,
330407 } ,
331408 }
332409}
@@ -338,7 +415,7 @@ where
338415 I : Read + Write + Unpin ,
339416 B : Body + ' static ,
340417 B :: Error : Into < Box < dyn StdError + Send + Sync > > ,
341- E : Http2ServerConnExec < S :: Future , B > ,
418+ E : HttpServerConnExec < S :: Future , B > ,
342419{
343420 /// Start a graceful shutdown process for this connection.
344421 ///
@@ -351,8 +428,12 @@ where
351428 pub fn graceful_shutdown ( self : Pin < & mut Self > ) {
352429 match self . project ( ) . state . project ( ) {
353430 UpgradeableConnStateProj :: ReadVersion { .. } => { }
431+ #[ cfg( feature = "http1" ) ]
354432 UpgradeableConnStateProj :: H1 { conn } => conn. graceful_shutdown ( ) ,
433+ #[ cfg( feature = "http2" ) ]
355434 UpgradeableConnStateProj :: H2 { conn } => conn. graceful_shutdown ( ) ,
435+ #[ cfg( any( not( feature = "http1" ) , not( feature = "http2" ) ) ) ]
436+ _ => unreachable ! ( ) ,
356437 }
357438 }
358439}
@@ -365,7 +446,7 @@ where
365446 B : Body + ' static ,
366447 B :: Error : Into < Box < dyn StdError + Send + Sync > > ,
367448 I : Read + Write + Unpin + Send + ' static ,
368- E : Http2ServerConnExec < S :: Future , B > ,
449+ E : HttpServerConnExec < S :: Future , B > ,
369450{
370451 type Output = Result < ( ) > ;
371452
@@ -382,34 +463,45 @@ where
382463 let ( version, io) = ready ! ( read_version. poll( cx) ) ?;
383464 let service = service. take ( ) . unwrap ( ) ;
384465 match version {
466+ #[ cfg( feature = "http1" ) ]
385467 Version :: H1 => {
386468 let conn = builder. http1 . serve_connection ( io, service) . with_upgrades ( ) ;
387469 this. state . set ( UpgradeableConnState :: H1 { conn } ) ;
388470 }
471+ #[ cfg( feature = "http2" ) ]
389472 Version :: H2 => {
390473 let conn = builder. http2 . serve_connection ( io, service) ;
391474 this. state . set ( UpgradeableConnState :: H2 { conn } ) ;
392475 }
476+ #[ cfg( any( not( feature = "http1" ) , not( feature = "http2" ) ) ) ]
477+ _ => return Poll :: Ready ( Err ( version. unsupported ( ) ) ) ,
393478 }
394479 }
480+ #[ cfg( feature = "http1" ) ]
395481 UpgradeableConnStateProj :: H1 { conn } => {
396482 return conn. poll ( cx) . map_err ( Into :: into) ;
397483 }
484+ #[ cfg( feature = "http2" ) ]
398485 UpgradeableConnStateProj :: H2 { conn } => {
399486 return conn. poll ( cx) . map_err ( Into :: into) ;
400487 }
488+ #[ cfg( any( not( feature = "http1" ) , not( feature = "http2" ) ) ) ]
489+ _ => unreachable ! ( ) ,
401490 }
402491 }
403492 }
404493}
405494
406495/// Http1 part of builder.
496+ #[ cfg( feature = "http1" ) ]
407497pub struct Http1Builder < ' a , E > {
408498 inner : & ' a mut Builder < E > ,
409499}
410500
501+ #[ cfg( feature = "http1" ) ]
411502impl < E > Http1Builder < ' _ , E > {
412503 /// Http2 configuration.
504+ #[ cfg( feature = "http2" ) ]
413505 pub fn http2 ( & mut self ) -> Http2Builder < ' _ , E > {
414506 Http2Builder {
415507 inner : & mut self . inner ,
@@ -524,6 +616,22 @@ impl<E> Http1Builder<'_, E> {
524616 }
525617
526618 /// Bind a connection together with a [`Service`].
619+ #[ cfg( feature = "http2" ) ]
620+ pub async fn serve_connection < I , S , B > ( & self , io : I , service : S ) -> Result < ( ) >
621+ where
622+ S : Service < Request < Incoming > , Response = Response < B > > ,
623+ S :: Future : ' static ,
624+ S :: Error : Into < Box < dyn StdError + Send + Sync > > ,
625+ B : Body + ' static ,
626+ B :: Error : Into < Box < dyn StdError + Send + Sync > > ,
627+ I : Read + Write + Unpin + ' static ,
628+ E : HttpServerConnExec < S :: Future , B > ,
629+ {
630+ self . inner . serve_connection ( io, service) . await
631+ }
632+
633+ /// Bind a connection together with a [`Service`].
634+ #[ cfg( not( feature = "http2" ) ) ]
527635 pub async fn serve_connection < I , S , B > ( & self , io : I , service : S ) -> Result < ( ) >
528636 where
529637 S : Service < Request < Incoming > , Response = Response < B > > ,
@@ -532,18 +640,20 @@ impl<E> Http1Builder<'_, E> {
532640 B : Body + ' static ,
533641 B :: Error : Into < Box < dyn StdError + Send + Sync > > ,
534642 I : Read + Write + Unpin + ' static ,
535- E : Http2ServerConnExec < S :: Future , B > ,
536643 {
537644 self . inner . serve_connection ( io, service) . await
538645 }
539646}
540647
541648/// Http2 part of builder.
649+ #[ cfg( feature = "http2" ) ]
542650pub struct Http2Builder < ' a , E > {
543651 inner : & ' a mut Builder < E > ,
544652}
545653
654+ #[ cfg( feature = "http2" ) ]
546655impl < E > Http2Builder < ' _ , E > {
656+ #[ cfg( feature = "http1" ) ]
547657 /// Http1 configuration.
548658 pub fn http1 ( & mut self ) -> Http1Builder < ' _ , E > {
549659 Http1Builder {
@@ -679,7 +789,7 @@ impl<E> Http2Builder<'_, E> {
679789 B : Body + ' static ,
680790 B :: Error : Into < Box < dyn StdError + Send + Sync > > ,
681791 I : Read + Write + Unpin + ' static ,
682- E : Http2ServerConnExec < S :: Future , B > ,
792+ E : HttpServerConnExec < S :: Future , B > ,
683793 {
684794 self . inner . serve_connection ( io, service) . await
685795 }
0 commit comments