]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: wrap client errors
authorkayos@tcp.direct <kayos@smoqueed.com>
Mon, 8 Jan 2024 07:42:00 +0000 (07:42 +0000)
committerCherry Mui <cherryyz@google.com>
Thu, 25 Jan 2024 15:53:12 +0000 (15:53 +0000)
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>
src/net/http/client.go
src/net/http/client_test.go
src/net/http/transport.go

index ee6de24fc19e4fbe8003a3def4fdcc426acd0ae4..45b9b915b4ae8c51464a6af191bcecfb4e1c5619 100644 (file)
@@ -726,7 +726,7 @@ func (c *Client) do(req *Request) (retres *Response, reterr error) {
                        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,
                                }
                        }
@@ -969,7 +969,7 @@ func (b *cancelTimerBody) Read(p []byte) (n int, err error) {
        }
        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,
                }
        }
index 7459b9cb6ed1df3a42d4ed54a54abc8748b3dffd..7c71da139a1e0fd0f0f8784e2f1e3a92ae87b6d2 100644 (file)
@@ -2127,3 +2127,22 @@ func testProbeZeroLengthBody(t *testing.T, mode testMode) {
                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)
+       }
+}
index 57c70e72f9522c93a643f48c649d2288c7e62640..6a1234e7f25525ec55609e2886851afc91303b56 100644 (file)
@@ -2556,15 +2556,17 @@ type writeRequest struct {
 }
 
 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.