From: Rick Arnold Date: Wed, 12 Feb 2014 15:59:58 +0000 (-0800) Subject: net/http: make responseAndError satisfy the net.Error interface X-Git-Tag: go1.3beta1~761 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=5e711b473c7aafd47dd0a3c3e66ceaa5bf07435b;p=gostls13.git net/http: make responseAndError satisfy the net.Error interface Allow clients to check for timeouts without relying on error substring matching. Fixes #6185. LGTM=bradfitz R=golang-codereviews, bradfitz CC=golang-codereviews https://golang.org/cl/55470048 --- diff --git a/src/pkg/net/http/transport.go b/src/pkg/net/http/transport.go index df17178235..2c312a77a0 100644 --- a/src/pkg/net/http/transport.go +++ b/src/pkg/net/http/transport.go @@ -869,6 +869,18 @@ type writeRequest struct { ch chan<- error } +type httpError struct { + err string + 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 } + +var errTimeout error = &httpError{err: "net/http: timeout awaiting response headers", timeout: true} +var errClosed error = &httpError{err: "net/http: transport closed before response was received"} + func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err error) { pc.t.setReqConn(req.Request, pc) pc.lk.Lock() @@ -939,11 +951,11 @@ WaitResponse: pconnDeadCh = nil // avoid spinning failTicker = time.After(100 * time.Millisecond) // arbitrary time to wait for resc case <-failTicker: - re = responseAndError{err: errors.New("net/http: transport closed before response was received")} + re = responseAndError{err: errClosed} break WaitResponse case <-respHeaderTimer: pc.close() - re = responseAndError{err: errors.New("net/http: timeout awaiting response headers")} + re = responseAndError{err: errTimeout} break WaitResponse case re = <-resc: break WaitResponse diff --git a/src/pkg/net/http/transport_test.go b/src/pkg/net/http/transport_test.go index da74ac9a0f..2678d71b1d 100644 --- a/src/pkg/net/http/transport_test.go +++ b/src/pkg/net/http/transport_test.go @@ -1237,6 +1237,20 @@ func TestTransportResponseHeaderTimeout(t *testing.T) { for i, tt := range tests { res, err := c.Get(ts.URL + tt.path) if err != nil { + uerr, ok := err.(*url.Error) + if !ok { + t.Errorf("error is not an url.Error; got: %#v", err) + continue + } + nerr, ok := uerr.Err.(net.Error) + if !ok { + t.Errorf("error does not satisfy net.Error interface; got: %#v", err) + continue + } + if !nerr.Timeout() { + t.Errorf("want timeout error; got: %q", nerr) + continue + } if strings.Contains(err.Error(), tt.wantErr) { continue }