From ecac827573ab1500551f2d7ffb98c06422abda9a Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 4 Jan 2017 21:03:24 +0000 Subject: [PATCH] net/http: make Server cancel its ReadTimeout between requests Fixes #18447 Change-Id: I5d60c3632a5ce625d3bac9d85533ce689e301707 Reviewed-on: https://go-review.googlesource.com/34813 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/net/http/serve_test.go | 37 +++++++++++++++++++++++++++++++++++++ src/net/http/server.go | 1 + 2 files changed, 38 insertions(+) diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index d8561f7c7f..c2be58108b 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -5089,3 +5089,40 @@ func testServerKeepAlivesEnabled(t *testing.T, h2 bool) { t.Fatalf("test server has active conns") } } + +// Issue 18447: test that the Server's ReadTimeout is stopped while +// the server's doing its 1-byte background read between requests, +// waiting for the connection to maybe close. +func TestServerCancelsReadTimeoutWhenIdle(t *testing.T) { + setParallel(t) + defer afterTest(t) + const timeout = 250 * time.Millisecond + ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) { + select { + case <-time.After(2 * timeout): + fmt.Fprint(w, "ok") + case <-r.Context().Done(): + fmt.Fprint(w, r.Context().Err()) + } + })) + ts.Config.ReadTimeout = timeout + ts.Start() + defer ts.Close() + + tr := &Transport{} + defer tr.CloseIdleConnections() + c := &Client{Transport: tr} + + res, err := c.Get(ts.URL) + if err != nil { + t.Fatal(err) + } + slurp, err := ioutil.ReadAll(res.Body) + res.Body.Close() + if err != nil { + t.Fatal(err) + } + if string(slurp) != "ok" { + t.Fatalf("Got: %q, want ok", slurp) + } +} diff --git a/src/net/http/server.go b/src/net/http/server.go index 6df9c260e4..bf1014134c 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -637,6 +637,7 @@ func (cr *connReader) startBackgroundRead() { panic("invalid concurrent Body.Read call") } cr.inRead = true + cr.conn.rwc.SetReadDeadline(time.Time{}) go cr.backgroundRead() } -- 2.48.1