mirror of
https://github.com/golang/go
synced 2024-11-22 08:04:39 -07:00
http: fix hanging bug with HEAD responses
The transport readLoop was waiting forever for the client to read the non-existent body before proceeding to read the next request. R=rsc CC=golang-dev https://golang.org/cl/4357051
This commit is contained in:
parent
2be13a80c7
commit
7c9c4fc3a1
@ -436,11 +436,12 @@ func (pc *persistConn) readLoop() {
|
|||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
alive = false
|
alive = false
|
||||||
}
|
}
|
||||||
|
hasBody := resp != nil && resp.ContentLength != 0
|
||||||
rc.ch <- responseAndError{resp, err}
|
rc.ch <- responseAndError{resp, err}
|
||||||
|
|
||||||
// Wait for the just-returned response body to be fully consumed
|
// Wait for the just-returned response body to be fully consumed
|
||||||
// before we race and peek on the underlying bufio reader.
|
// before we race and peek on the underlying bufio reader.
|
||||||
if alive {
|
if alive && hasBody {
|
||||||
<-resp.Body.(*bodyEOFSignal).ch
|
<-resp.Body.(*bodyEOFSignal).ch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -512,7 +513,7 @@ func responseIsKeepAlive(res *Response) bool {
|
|||||||
// the response body with a bodyEOFSignal-wrapped version.
|
// the response body with a bodyEOFSignal-wrapped version.
|
||||||
func readResponseWithEOFSignal(r *bufio.Reader, requestMethod string) (resp *Response, err os.Error) {
|
func readResponseWithEOFSignal(r *bufio.Reader, requestMethod string) (resp *Response, err os.Error) {
|
||||||
resp, err = ReadResponse(r, requestMethod)
|
resp, err = ReadResponse(r, requestMethod)
|
||||||
if err == nil {
|
if err == nil && resp.ContentLength != 0 {
|
||||||
resp.Body = &bodyEOFSignal{resp.Body, make(chan bool, 1), false}
|
resp.Body = &bodyEOFSignal{resp.Body, make(chan bool, 1), false}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -261,6 +261,34 @@ func TestTransportServerClosingUnexpectedly(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestTransportHeadResponses verifies that we deal with Content-Lengths
|
||||||
|
// with no bodies properly
|
||||||
|
func TestTransportHeadResponses(t *testing.T) {
|
||||||
|
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
|
||||||
|
if r.Method != "HEAD" {
|
||||||
|
panic("expected HEAD; got " + r.Method)
|
||||||
|
}
|
||||||
|
w.Header().Set("Content-Length", "123")
|
||||||
|
w.WriteHeader(200)
|
||||||
|
}))
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
tr := &Transport{DisableKeepAlives: false}
|
||||||
|
c := &Client{Transport: tr}
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
res, err := c.Head(ts.URL)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error on loop %d: %v", i, err)
|
||||||
|
}
|
||||||
|
if e, g := "123", res.Header.Get("Content-Length"); e != g {
|
||||||
|
t.Errorf("loop %d: expected Content-Length header of %q, got %q", e, g)
|
||||||
|
}
|
||||||
|
if e, g := int64(0), res.ContentLength; e != g {
|
||||||
|
t.Errorf("loop %d: expected res.ContentLength of %v, got %v", e, g)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestTransportNilURL(t *testing.T) {
|
func TestTransportNilURL(t *testing.T) {
|
||||||
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
|
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
|
||||||
fmt.Fprintf(w, "Hi")
|
fmt.Fprintf(w, "Hi")
|
||||||
|
Loading…
Reference in New Issue
Block a user