@@ -610,6 +610,105 @@ public final class Http2ConnectionTest {
610
610
assertThat (synStream .headerBlock ).isEqualTo (headerEntries ("a" , "artichaut" ));
611
611
}
612
612
613
+ /** A server RST_STREAM shouldn't prevent the client from consuming the response body. */
614
+ @ Test public void serverResponseBodyRstStream () throws Exception {
615
+ // write the mocking script
616
+ peer .sendFrame ().settings (new Settings ());
617
+ peer .acceptFrame (); // ACK
618
+ peer .acceptFrame (); // SYN_STREAM
619
+ peer .acceptFrame (); // PING
620
+ peer .sendFrame ().headers (false , 3 , headerEntries ("a" , "android" ));
621
+ peer .sendFrame ().data (true , 3 , new Buffer ().writeUtf8 ("robot" ), 5 );
622
+ peer .sendFrame ().rstStream (3 , ErrorCode .NO_ERROR );
623
+ peer .sendFrame ().ping (true , AWAIT_PING , 0 ); // PONG
624
+ peer .play ();
625
+
626
+ // play it back
627
+ Http2Connection connection = connect (peer );
628
+ Http2Stream stream = connection .newStream (headerEntries (), false );
629
+ connection .writePingAndAwaitPong ();
630
+ assertThat (stream .takeHeaders ()).isEqualTo (Headers .of ("a" , "android" ));
631
+ BufferedSource source = Okio .buffer (stream .getSource ());
632
+ assertThat (source .readUtf8 (5 )).isEqualTo ("robot" );
633
+ stream .getSink ().close ();
634
+ assertThat (connection .openStreamCount ()).isEqualTo (0 );
635
+
636
+ // verify the peer received what was expected
637
+ InFrame synStream = peer .takeFrame ();
638
+ assertThat (synStream .type ).isEqualTo (Http2 .TYPE_HEADERS );
639
+ InFrame ping = peer .takeFrame ();
640
+ assertThat (ping .type ).isEqualTo (Http2 .TYPE_PING );
641
+ }
642
+
643
+ /** A server RST_STREAM shouldn't prevent the client from consuming trailers. */
644
+ @ Test public void serverTrailersRstStream () throws Exception {
645
+ // write the mocking script
646
+ peer .sendFrame ().settings (new Settings ());
647
+ peer .acceptFrame (); // ACK
648
+ peer .acceptFrame (); // SYN_STREAM
649
+ peer .acceptFrame (); // PING
650
+ peer .sendFrame ().headers (false , 3 , headerEntries ("a" , "android" ));
651
+ peer .sendFrame ().headers (true , 3 , headerEntries ("z" , "zebra" ));
652
+ peer .sendFrame ().rstStream (3 , ErrorCode .NO_ERROR );
653
+ peer .sendFrame ().ping (true , AWAIT_PING , 0 ); // PONG
654
+ peer .play ();
655
+
656
+ // play it back
657
+ Http2Connection connection = connect (peer );
658
+ Http2Stream stream = connection .newStream (headerEntries (), true );
659
+ connection .writePingAndAwaitPong ();
660
+ assertThat (stream .takeHeaders ()).isEqualTo (Headers .of ("a" , "android" ));
661
+ stream .getSink ().close ();
662
+ assertThat (stream .trailers ()).isEqualTo (Headers .of ("z" , "zebra" ));
663
+ assertThat (connection .openStreamCount ()).isEqualTo (0 );
664
+
665
+ // verify the peer received what was expected
666
+ InFrame synStream = peer .takeFrame ();
667
+ assertThat (synStream .type ).isEqualTo (Http2 .TYPE_HEADERS );
668
+ InFrame ping = peer .takeFrame ();
669
+ assertThat (ping .type ).isEqualTo (Http2 .TYPE_PING );
670
+ }
671
+
672
+ /**
673
+ * A server RST_STREAM shouldn't prevent the client from consuming the response body, even if it
674
+ * follows a truncated request body.
675
+ */
676
+ @ Test public void clientRequestBodyServerResponseBodyRstStream () throws Exception {
677
+ // write the mocking script
678
+ peer .sendFrame ().settings (new Settings ());
679
+ peer .acceptFrame (); // ACK
680
+ peer .acceptFrame (); // SYN_STREAM
681
+ peer .acceptFrame (); // PING
682
+ peer .sendFrame ().headers (false , 3 , headerEntries ("a" , "android" ));
683
+ peer .sendFrame ().data (true , 3 , new Buffer ().writeUtf8 ("robot" ), 5 );
684
+ peer .sendFrame ().rstStream (3 , ErrorCode .NO_ERROR );
685
+ peer .sendFrame ().ping (true , AWAIT_PING , 0 ); // PONG
686
+ peer .play ();
687
+
688
+ // play it back
689
+ Http2Connection connection = connect (peer );
690
+ Http2Stream stream = connection .newStream (headerEntries (), true );
691
+ connection .writePingAndAwaitPong ();
692
+ BufferedSink sink = Okio .buffer (stream .getSink ());
693
+ sink .writeUtf8 ("abc" );
694
+ try {
695
+ sink .close ();
696
+ fail ();
697
+ } catch (StreamResetException expected ) {
698
+ assertThat (expected .errorCode ).isEqualTo (ErrorCode .NO_ERROR );
699
+ }
700
+ assertThat (stream .takeHeaders ()).isEqualTo (Headers .of ("a" , "android" ));
701
+ BufferedSource source = Okio .buffer (stream .getSource ());
702
+ assertThat (source .readUtf8 (5 )).isEqualTo ("robot" );
703
+ assertThat (connection .openStreamCount ()).isEqualTo (0 );
704
+
705
+ // verify the peer received what was expected
706
+ InFrame synStream = peer .takeFrame ();
707
+ assertThat (synStream .type ).isEqualTo (Http2 .TYPE_HEADERS );
708
+ InFrame ping = peer .takeFrame ();
709
+ assertThat (ping .type ).isEqualTo (Http2 .TYPE_PING );
710
+ }
711
+
613
712
@ Test public void serverWritesTrailersWithData () throws Exception {
614
713
// We buffer some outbound data and headers and confirm that the END_STREAM flag comes with the
615
714
// headers (and not with the data).
0 commit comments