1
0
mirror of https://github.com/golang/go synced 2024-11-19 14:54:43 -07:00

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
This commit is contained in:
Rick Arnold 2014-02-12 07:59:58 -08:00 committed by Brad Fitzpatrick
parent c507601102
commit 5e711b473c
2 changed files with 28 additions and 2 deletions

View File

@ -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

View File

@ -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
}