Skip to content

Commit 94b0308

Browse files
committed
net/http: add tests for Server.ReadTimeout and server.WriteTimeout
We don't seem to have tests verifying that handler reads from the request body or writes to the response body time out properly. Add some. For #49837 For #56478 Change-Id: I0828edd6c86b071073fd1b22ccbb24f86114ab94 Reviewed-on: https://go-review.googlesource.com/c/go/+/446255 Reviewed-by: Brad Fitzpatrick <[email protected]> Reviewed-by: Bryan Mills <[email protected]> Run-TryBot: Damien Neil <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 2cea6cd commit 94b0308

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

src/net/http/serve_test.go

+69
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,75 @@ func testServerTimeoutsWithTimeout(t *testing.T, timeout time.Duration, mode tes
736736
return nil
737737
}
738738

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+
739808
// Test that the HTTP/2 server handles Server.WriteTimeout (Issue 18437)
740809
func TestWriteDeadlineExtendedOnNewRequest(t *testing.T) {
741810
run(t, testWriteDeadlineExtendedOnNewRequest)

0 commit comments

Comments
 (0)