Fixes #50856
Change-Id: I7fe89fcce223e1571debb73436f8aeb3bfbe4b9f
GitHub-Last-Rev:
be570e7883be06adbd227a1dfe63a80e384d96f6
GitHub-Pull-Request: golang/go#63448
Reviewed-on: https://go-review.googlesource.com/c/go/+/533119
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: qiulaidongfeng <2645477756@qq.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
reqBodyClosed = true
if !deadline.IsZero() && didTimeout() {
err = &httpError{
- err: err.Error() + " (Client.Timeout exceeded while awaiting headers)",
+ err: fmt.Errorf("%w (Client.Timeout exceeded while awaiting headers)", err),
timeout: true,
}
}
}
if b.reqDidTimeout() {
err = &httpError{
- err: err.Error() + " (Client.Timeout or context cancellation while reading body)",
+ err: fmt.Errorf("%w (Client.Timeout exceeded or context cancellation while reading body)", err),
timeout: true,
}
}
t.Fatalf("server got body %q, want %q", gotBody, content)
}
}
+
+func TestClientTimeoutReturnsContextDeadlineExceeded(t *testing.T) {
+ run(t, testClientTimeoutReturnsContextDeadlineExceeded)
+}
+func testClientTimeoutReturnsContextDeadlineExceeded(t *testing.T, mode testMode) {
+ doneCh := make(chan struct{})
+ defer close(doneCh)
+ cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
+ <-doneCh
+ w.WriteHeader(200)
+ }))
+ // check that, upon exceeding Client.Timeout, the returned error is context.DeadlineExceeded.
+ cst.c.Timeout = 1 * time.Millisecond
+ req, _ := NewRequest("GET", cst.ts.URL, nil)
+ _, err := cst.c.Do(req)
+ if !errors.Is(err, context.DeadlineExceeded) {
+ t.Fatalf("expected context.DeadlineExceeded, got %v", err)
+ }
+}
}
type httpError struct {
- err string
+ err error
timeout bool
}
-func (e *httpError) Error() string { return e.err }
-func (e *httpError) Timeout() bool { return e.timeout }
-func (e *httpError) Temporary() bool { return true }
+func (e *httpError) Error() string { return e.err.Error() }
+func (e *httpError) Timeout() bool { return e.timeout }
+func (e *httpError) Temporary() bool { return true }
+func (e *httpError) Is(target error) bool { return errors.Is(e.err, target) }
+func (e *httpError) Unwrap() error { return e.err }
-var errTimeout error = &httpError{err: "net/http: timeout awaiting response headers", timeout: true}
+var errTimeout error = &httpError{err: errors.New("net/http: timeout awaiting response headers"), timeout: true}
// errRequestCanceled is set to be identical to the one from h2 to facilitate
// testing.