aboutsummaryrefslogtreecommitdiff
path: root/src/net/http/serve_test.go
diff options
context:
space:
mode:
authorCharlie Getzen <charlie@bolt.com>2021-11-05 17:27:35 +0000
committerDamien Neil <dneil@google.com>2021-11-05 21:18:28 +0000
commit4c7cafdd03426bc2b9fb1275d13d0abc755dde16 (patch)
tree0c7c1070022a37cc86e0c3bd3ce3230ea246eef8 /src/net/http/serve_test.go
parent091948a55fb198be4202c21a5809ec68d77f70c4 (diff)
downloadgo-4c7cafdd03426bc2b9fb1275d13d0abc755dde16.tar.gz
go-4c7cafdd03426bc2b9fb1275d13d0abc755dde16.zip
net/http: distinguish between timeouts and client hangups in TimeoutHandler
Fixes #48948 Change-Id: I411e3be99c7979ae289fd937388aae63d81adb59 GitHub-Last-Rev: 14abd7e4d774ed5ef63aa0a69e80fbc8b5a5af26 GitHub-Pull-Request: golang/go#48993 Reviewed-on: https://go-review.googlesource.com/c/go/+/356009 Reviewed-by: Damien Neil <dneil@google.com> Trust: Damien Neil <dneil@google.com> Trust: Ian Lance Taylor <iant@golang.org> Run-TryBot: Damien Neil <dneil@google.com> TryBot-Result: Go Bot <gobot@golang.org>
Diffstat (limited to 'src/net/http/serve_test.go')
-rw-r--r--src/net/http/serve_test.go63
1 files changed, 57 insertions, 6 deletions
diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go
index a98d6c313f..e8fb77446c 100644
--- a/src/net/http/serve_test.go
+++ b/src/net/http/serve_test.go
@@ -2274,6 +2274,18 @@ func TestRequestBodyTimeoutClosesConnection(t *testing.T) {
}
}
+// cancelableTimeoutContext overwrites the error message to DeadlineExceeded
+type cancelableTimeoutContext struct {
+ context.Context
+}
+
+func (c cancelableTimeoutContext) Err() error {
+ if c.Context.Err() != nil {
+ return context.DeadlineExceeded
+ }
+ return nil
+}
+
func TestTimeoutHandler_h1(t *testing.T) { testTimeoutHandler(t, h1Mode) }
func TestTimeoutHandler_h2(t *testing.T) { testTimeoutHandler(t, h2Mode) }
func testTimeoutHandler(t *testing.T, h2 bool) {
@@ -2286,8 +2298,9 @@ func testTimeoutHandler(t *testing.T, h2 bool) {
_, werr := w.Write([]byte("hi"))
writeErrors <- werr
})
- timeout := make(chan time.Time, 1) // write to this to force timeouts
- cst := newClientServerTest(t, h2, NewTestTimeoutHandler(sayHi, timeout))
+ ctx, cancel := context.WithCancel(context.Background())
+ h := NewTestTimeoutHandler(sayHi, cancelableTimeoutContext{ctx})
+ cst := newClientServerTest(t, h2, h)
defer cst.close()
// Succeed without timing out:
@@ -2308,7 +2321,8 @@ func testTimeoutHandler(t *testing.T, h2 bool) {
}
// Times out:
- timeout <- time.Time{}
+ cancel()
+
res, err = cst.c.Get(cst.ts.URL)
if err != nil {
t.Error(err)
@@ -2429,8 +2443,9 @@ func TestTimeoutHandlerRaceHeaderTimeout(t *testing.T) {
_, werr := w.Write([]byte("hi"))
writeErrors <- werr
})
- timeout := make(chan time.Time, 1) // write to this to force timeouts
- cst := newClientServerTest(t, h1Mode, NewTestTimeoutHandler(sayHi, timeout))
+ ctx, cancel := context.WithCancel(context.Background())
+ h := NewTestTimeoutHandler(sayHi, cancelableTimeoutContext{ctx})
+ cst := newClientServerTest(t, h1Mode, h)
defer cst.close()
// Succeed without timing out:
@@ -2451,7 +2466,8 @@ func TestTimeoutHandlerRaceHeaderTimeout(t *testing.T) {
}
// Times out:
- timeout <- time.Time{}
+ cancel()
+
res, err = cst.c.Get(cst.ts.URL)
if err != nil {
t.Error(err)
@@ -2501,6 +2517,41 @@ func TestTimeoutHandlerStartTimerWhenServing(t *testing.T) {
}
}
+func TestTimeoutHandlerContextCanceled(t *testing.T) {
+ setParallel(t)
+ defer afterTest(t)
+ sendHi := make(chan bool, 1)
+ writeErrors := make(chan error, 1)
+ sayHi := HandlerFunc(func(w ResponseWriter, r *Request) {
+ w.Header().Set("Content-Type", "text/plain")
+ <-sendHi
+ _, werr := w.Write([]byte("hi"))
+ writeErrors <- werr
+ })
+ ctx, cancel := context.WithTimeout(context.Background(), 1*time.Hour)
+ h := NewTestTimeoutHandler(sayHi, ctx)
+ cancel()
+ cst := newClientServerTest(t, h1Mode, h)
+ defer cst.close()
+
+ // Succeed without timing out:
+ sendHi <- true
+ res, err := cst.c.Get(cst.ts.URL)
+ if err != nil {
+ t.Error(err)
+ }
+ if g, e := res.StatusCode, StatusServiceUnavailable; g != e {
+ t.Errorf("got res.StatusCode %d; expected %d", g, e)
+ }
+ body, _ := io.ReadAll(res.Body)
+ if g, e := string(body), ""; g != e {
+ t.Errorf("got body %q; expected %q", g, e)
+ }
+ if g, e := <-writeErrors, context.Canceled; g != e {
+ t.Errorf("got unexpected Write error on first request: %v", g)
+ }
+}
+
// https://golang.org/issue/15948
func TestTimeoutHandlerEmptyResponse(t *testing.T) {
setParallel(t)