Skip to content

Commit 19e0799

Browse files
odeke-embradfitz
authored andcommitted
net/http: fix and lock-in Client.Do docs on request cancelation
Fixes the docs to correctly match the implementation and also adds a test locking-in the behavior to prevent any accidental future regressions on the docs. Fixes #33545 Change-Id: I6fdac6048cce8ac99beaa2db0dfc81d0dccc10f1 Reviewed-on: https://go-review.googlesource.com/c/go/+/200798 Run-TryBot: Emmanuel Odeke <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]>
1 parent b649bdc commit 19e0799

File tree

2 files changed

+57
-2
lines changed

2 files changed

+57
-2
lines changed

src/net/http/client.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -434,8 +434,8 @@ func Get(url string) (resp *Response, err error) {
434434
// An error is returned if the Client's CheckRedirect function fails
435435
// or if there was an HTTP protocol error. A non-2xx response doesn't
436436
// cause an error. Any returned error will be of type *url.Error. The
437-
// url.Error value's Timeout method will report true if request timed
438-
// out or was canceled.
437+
// url.Error value's Timeout method will report true if the request
438+
// timed out.
439439
//
440440
// When err is nil, resp always contains a non-nil resp.Body.
441441
// Caller should close resp.Body when done reading from it.

src/net/http/client_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1936,3 +1936,58 @@ func TestClientPropagatesTimeoutToContext(t *testing.T) {
19361936
}
19371937
c.Get("https://example.tld/")
19381938
}
1939+
1940+
func TestClientDoCanceledVsTimeout_h1(t *testing.T) {
1941+
testClientDoCanceledVsTimeout(t, h1Mode)
1942+
}
1943+
1944+
func TestClientDoCanceledVsTimeout_h2(t *testing.T) {
1945+
testClientDoCanceledVsTimeout(t, h2Mode)
1946+
}
1947+
1948+
// Issue 33545: lock-in the behavior promised by Client.Do's
1949+
// docs about request cancelation vs timing out.
1950+
func testClientDoCanceledVsTimeout(t *testing.T, h2 bool) {
1951+
defer afterTest(t)
1952+
cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
1953+
w.Write([]byte("Hello, World!"))
1954+
}))
1955+
defer cst.close()
1956+
1957+
cases := []string{"timeout", "canceled"}
1958+
1959+
for _, name := range cases {
1960+
t.Run(name, func(t *testing.T) {
1961+
var ctx context.Context
1962+
var cancel func()
1963+
if name == "timeout" {
1964+
ctx, cancel = context.WithTimeout(context.Background(), -time.Nanosecond)
1965+
} else {
1966+
ctx, cancel = context.WithCancel(context.Background())
1967+
cancel()
1968+
}
1969+
defer cancel()
1970+
1971+
req, _ := NewRequestWithContext(ctx, "GET", cst.ts.URL, nil)
1972+
_, err := cst.c.Do(req)
1973+
if err == nil {
1974+
t.Fatal("Unexpectedly got a nil error")
1975+
}
1976+
1977+
ue := err.(*url.Error)
1978+
1979+
var wantIsTimeout bool
1980+
var wantErr error = context.Canceled
1981+
if name == "timeout" {
1982+
wantErr = context.DeadlineExceeded
1983+
wantIsTimeout = true
1984+
}
1985+
if g, w := ue.Timeout(), wantIsTimeout; g != w {
1986+
t.Fatalf("url.Timeout() = %t, want %t", g, w)
1987+
}
1988+
if g, w := ue.Err, wantErr; g != w {
1989+
t.Errorf("url.Error.Err = %v; want %v", g, w)
1990+
}
1991+
})
1992+
}
1993+
}

0 commit comments

Comments
 (0)