@@ -14,10 +14,10 @@ use http::{
14
14
use http_body_util:: BodyExt ;
15
15
use hyper:: {
16
16
body:: { Bytes , Incoming } ,
17
- server:: conn:: http1,
17
+ server:: conn:: { http1, http2 } ,
18
18
service:: service_fn,
19
19
} ;
20
- use hyper_util:: rt:: TokioIo ;
20
+ use hyper_util:: rt:: { TokioExecutor , TokioIo } ;
21
21
use spin_app:: { APP_DESCRIPTION_KEY , APP_NAME_KEY } ;
22
22
use spin_factor_outbound_http:: { OutboundHttpFactor , SelfRequestOrigin } ;
23
23
use spin_factors:: RuntimeFactors ;
@@ -206,7 +206,7 @@ impl<F: RuntimeFactors> HttpServer<F> {
206
206
loop {
207
207
let ( stream, client_addr) = listener. accept ( ) . await ?;
208
208
self . clone ( )
209
- . serve_connection ( stream, Scheme :: HTTP , client_addr) ;
209
+ . http1_serve_connection ( stream, Scheme :: HTTP , client_addr) ;
210
210
}
211
211
}
212
212
@@ -220,9 +220,15 @@ impl<F: RuntimeFactors> HttpServer<F> {
220
220
loop {
221
221
let ( stream, client_addr) = listener. accept ( ) . await ?;
222
222
match acceptor. accept ( stream) . await {
223
- Ok ( stream) => self
224
- . clone ( )
225
- . serve_connection ( stream, Scheme :: HTTPS , client_addr) ,
223
+ Ok ( stream) => {
224
+ if stream. get_ref ( ) . 1 . alpn_protocol ( ) == Some ( b"h2" ) {
225
+ self . clone ( )
226
+ . http2_serve_connection ( stream, Scheme :: HTTPS , client_addr)
227
+ } else {
228
+ self . clone ( )
229
+ . http1_serve_connection ( stream, Scheme :: HTTPS , client_addr)
230
+ }
231
+ }
226
232
Err ( err) => tracing:: error!( ?err, "Failed to start TLS session" ) ,
227
233
}
228
234
}
@@ -403,7 +409,7 @@ impl<F: RuntimeFactors> HttpServer<F> {
403
409
. body ( body:: empty ( ) ) ?)
404
410
}
405
411
406
- fn serve_connection < S : AsyncRead + AsyncWrite + Unpin + Send + ' static > (
412
+ fn http1_serve_connection < S : AsyncRead + AsyncWrite + Unpin + Send + ' static > (
407
413
self : Arc < Self > ,
408
414
stream : S ,
409
415
server_scheme : Scheme ,
@@ -424,7 +430,32 @@ impl<F: RuntimeFactors> HttpServer<F> {
424
430
)
425
431
. await
426
432
{
427
- tracing:: warn!( "Error serving HTTP connection: {err:?}" ) ;
433
+ tracing:: warn!( "Error serving HTTP1 connection: {err:?}" ) ;
434
+ }
435
+ } ) ;
436
+ }
437
+
438
+ fn http2_serve_connection < S : AsyncRead + AsyncWrite + Unpin + Send + ' static > (
439
+ self : Arc < Self > ,
440
+ stream : S ,
441
+ server_scheme : Scheme ,
442
+ client_addr : SocketAddr ,
443
+ ) {
444
+ task:: spawn ( async move {
445
+ if let Err ( err) = http2:: Builder :: new ( TokioExecutor :: new ( ) )
446
+ . serve_connection (
447
+ TokioIo :: new ( stream) ,
448
+ service_fn ( move |request| {
449
+ self . clone ( ) . instrumented_service_fn (
450
+ server_scheme. clone ( ) ,
451
+ client_addr,
452
+ request,
453
+ )
454
+ } ) ,
455
+ )
456
+ . await
457
+ {
458
+ tracing:: warn!( "Error serving HTTP2 connection: {err:?}" ) ;
428
459
}
429
460
} ) ;
430
461
}
0 commit comments