@@ -2552,7 +2552,7 @@ mod conn {
25522552 }
25532553
25542554 #[ tokio:: test]
2555- async fn http2_responds_before_consuming_request_body ( ) {
2555+ async fn http2_responds_before_consuming_request_body_no_trailers ( ) {
25562556 // Test that a early-response from server works correctly (request body wasn't fully consumed).
25572557 // https://github.com/hyperium/hyper/issues/2872
25582558 use hyper:: service:: service_fn;
@@ -2596,15 +2596,96 @@ mod conn {
25962596 let resp = client. send_request ( req) . await . expect ( "send_request" ) ;
25972597 assert ! ( resp. status( ) . is_success( ) ) ;
25982598
2599- let mut body = String :: new ( ) ;
2600- concat ( resp. into_body ( ) )
2599+ let ( body, trailers) = crate :: concat_with_trailers ( resp. into_body ( ) ) . await . unwrap ( ) ;
2600+ assert_eq ! ( body. as_ref( ) , b"No bread for you!" ) ;
2601+ assert ! ( trailers. is_none( ) ) ;
2602+ }
2603+
2604+ #[ tokio:: test]
2605+ async fn http2_responds_before_consuming_request_body_with_trailers ( ) {
2606+ // Test that a early-response from server works correctly (request body wasn't fully consumed).
2607+ // https://github.com/hyperium/hyper/issues/2872
2608+ use hyper:: body:: { Body , Frame , SizeHint } ;
2609+ use hyper:: header:: { HeaderMap , HeaderValue } ;
2610+ use hyper:: service:: service_fn;
2611+
2612+ let _ = pretty_env_logger:: try_init ( ) ;
2613+
2614+ let ( listener, addr) = setup_tk_test_server ( ) . await ;
2615+
2616+ /// An `HttpBody` implementation whose `is_end_stream()` will
2617+ /// return `true` after sending trailers.
2618+ pub struct TrailersBody ( Option < HeaderMap > ) ;
2619+
2620+ impl Body for TrailersBody {
2621+ type Data = bytes:: Bytes ;
2622+ type Error = hyper:: Error ;
2623+
2624+ fn poll_frame (
2625+ mut self : Pin < & mut Self > ,
2626+ _cx : & mut Context < ' _ > ,
2627+ ) -> Poll < Option < Result < Frame < Self :: Data > , Self :: Error > > > {
2628+ if let Some ( trailers) = self . 0 . take ( ) {
2629+ Poll :: Ready ( Some ( Ok ( Frame :: trailers ( trailers) ) ) )
2630+ } else {
2631+ Poll :: Ready ( None )
2632+ }
2633+ }
2634+
2635+ fn is_end_stream ( & self ) -> bool {
2636+ self . 0 . is_none ( )
2637+ }
2638+
2639+ fn size_hint ( & self ) -> SizeHint {
2640+ SizeHint :: with_exact ( 0 )
2641+ }
2642+ }
2643+
2644+ // Spawn an HTTP2 server that responds before reading the whole request body.
2645+ // It's normal case to decline the request due to headers or size of the body.
2646+ tokio:: spawn ( async move {
2647+ let sock = TokioIo :: new ( listener. accept ( ) . await . unwrap ( ) . 0 ) ;
2648+ hyper:: server:: conn:: http2:: Builder :: new ( TokioExecutor )
2649+ . timer ( TokioTimer )
2650+ . serve_connection (
2651+ sock,
2652+ service_fn ( |_req| async move {
2653+ let mut trailers = HeaderMap :: new ( ) ;
2654+ trailers. insert ( "grpc" , HeaderValue :: from_static ( "0" ) ) ;
2655+ let body = TrailersBody ( Some ( trailers) ) ;
2656+ Ok :: < _ , hyper:: Error > ( http:: Response :: new ( body) )
2657+ } ) ,
2658+ )
2659+ . await
2660+ . expect ( "serve_connection" ) ;
2661+ } ) ;
2662+
2663+ let io = tcp_connect ( & addr) . await . expect ( "tcp connect" ) ;
2664+ let ( mut client, conn) = conn:: http2:: Builder :: new ( TokioExecutor )
2665+ . timer ( TokioTimer )
2666+ . handshake ( io)
26012667 . await
2602- . unwrap ( )
2603- . reader ( )
2604- . read_to_string ( & mut body)
2605- . unwrap ( ) ;
2668+ . expect ( "http handshake" ) ;
2669+
2670+ tokio:: spawn ( async move {
2671+ conn. await . expect ( "client conn shouldn't error" ) ;
2672+ } ) ;
2673+
2674+ // Use a channel to keep request stream open
2675+ let ( _tx, recv) = mpsc:: channel :: < Result < Frame < Bytes > , Box < dyn Error + Send + Sync > > > ( 0 ) ;
2676+ let req = Request :: post ( "/a" ) . body ( StreamBody :: new ( recv) ) . unwrap ( ) ;
2677+ let resp = client. send_request ( req) . await . expect ( "send_request" ) ;
2678+ assert ! ( resp. status( ) . is_success( ) ) ;
2679+
2680+ let ( body, trailers) = crate :: concat_with_trailers ( resp. into_body ( ) ) . await . unwrap ( ) ;
2681+
2682+ // No body:
2683+ assert ! ( body. is_empty( ) ) ;
26062684
2607- assert_eq ! ( & body, "No bread for you!" ) ;
2685+ // Have our `grpc` trailer:
2686+ let trailers = trailers. expect ( "response has trailers" ) ;
2687+ assert_eq ! ( trailers. len( ) , 1 ) ;
2688+ assert_eq ! ( trailers. get( "grpc" ) . unwrap( ) , "0" ) ;
26082689 }
26092690
26102691 #[ tokio:: test]
0 commit comments