@@ -736,6 +736,75 @@ func testServerTimeoutsWithTimeout(t *testing.T, timeout time.Duration, mode tes
736
736
return nil
737
737
}
738
738
739
+ func TestServerReadTimeout (t * testing.T ) { run (t , testServerReadTimeout ) }
740
+ func testServerReadTimeout (t * testing.T , mode testMode ) {
741
+ if mode == http2Mode {
742
+ t .Skip ("https://go.dev/issue/49837" )
743
+ }
744
+ respBody := "response body"
745
+ cst := newClientServerTest (t , mode , HandlerFunc (func (res ResponseWriter , req * Request ) {
746
+ _ , err := io .Copy (io .Discard , req .Body )
747
+ if ! errors .Is (err , os .ErrDeadlineExceeded ) {
748
+ t .Errorf ("server timed out reading request body: got err %v; want os.ErrDeadlineExceeded" , err )
749
+ }
750
+ res .Write ([]byte (respBody ))
751
+ }), func (ts * httptest.Server ) {
752
+ ts .Config .ReadTimeout = 5 * time .Millisecond
753
+ })
754
+ pr , pw := io .Pipe ()
755
+ res , err := cst .c .Post (cst .ts .URL , "text/apocryphal" , pr )
756
+ if err != nil {
757
+ t .Fatal (err )
758
+ }
759
+ defer res .Body .Close ()
760
+ got , err := io .ReadAll (res .Body )
761
+ if string (got ) != respBody || err != nil {
762
+ t .Errorf ("client read response body: %q, %v; want %q, nil" , string (got ), err , respBody )
763
+ }
764
+ pw .Close ()
765
+ }
766
+
767
+ func TestServerWriteTimeout (t * testing.T ) { run (t , testServerWriteTimeout ) }
768
+ func testServerWriteTimeout (t * testing.T , mode testMode ) {
769
+ if mode == http2Mode {
770
+ t .Skip ("https://go.dev/issue/56478" )
771
+ }
772
+ for timeout := 5 * time .Millisecond ; ; timeout *= 2 {
773
+ errc := make (chan error , 2 )
774
+ cst := newClientServerTest (t , mode , HandlerFunc (func (res ResponseWriter , req * Request ) {
775
+ errc <- nil
776
+ _ , err := io .Copy (res , neverEnding ('a' ))
777
+ errc <- err
778
+ }), func (ts * httptest.Server ) {
779
+ ts .Config .WriteTimeout = timeout
780
+ })
781
+ res , err := cst .c .Get (cst .ts .URL )
782
+ if err != nil {
783
+ // Probably caused by the write timeout expiring before the handler runs.
784
+ t .Logf ("Get error, retrying: %v" , err )
785
+ cst .close ()
786
+ continue
787
+ }
788
+ defer res .Body .Close ()
789
+ _ , err = io .Copy (io .Discard , res .Body )
790
+ if err == nil {
791
+ t .Errorf ("client reading from truncated request body: got nil error, want non-nil" )
792
+ }
793
+ cst .close ()
794
+ select {
795
+ case <- errc :
796
+ err = <- errc // io.Copy error
797
+ if ! errors .Is (err , os .ErrDeadlineExceeded ) {
798
+ t .Errorf ("server timed out writing request body: got err %v; want os.ErrDeadlineExceeded" , err )
799
+ }
800
+ return
801
+ default :
802
+ // The write timeout expired before the handler started.
803
+ t .Logf ("handler didn't run, retrying" )
804
+ }
805
+ }
806
+ }
807
+
739
808
// Test that the HTTP/2 server handles Server.WriteTimeout (Issue 18437)
740
809
func TestWriteDeadlineExtendedOnNewRequest (t * testing.T ) {
741
810
run (t , testWriteDeadlineExtendedOnNewRequest )
0 commit comments