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:
parent
c507601102
commit
5e711b473c
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user