aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@golang.org>2011-04-04 16:58:11 -0700
committerBrad Fitzpatrick <bradfitz@golang.org>2011-04-04 16:58:11 -0700
commit7c9c4fc3a189399385960254facfab6feff55d5f (patch)
treeb72e214a87fcc2110626ed9f6fc444b176bcbe6a
parent2be13a80c78e22a89fba27450cf813a2fe22ebca (diff)
downloadgo-7c9c4fc3a189399385960254facfab6feff55d5f.tar.gz
go-7c9c4fc3a189399385960254facfab6feff55d5f.zip
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
-rw-r--r--src/pkg/http/transport.go5
-rw-r--r--src/pkg/http/transport_test.go28
2 files changed, 31 insertions, 2 deletions
diff --git a/src/pkg/http/transport.go b/src/pkg/http/transport.go
index 7f85c8c281..fa4120e27a 100644
--- a/src/pkg/http/transport.go
+++ b/src/pkg/http/transport.go
@@ -436,11 +436,12 @@ func (pc *persistConn) readLoop() {
} else if err != nil {
alive = false
}
+ hasBody := resp != nil && resp.ContentLength != 0
rc.ch <- responseAndError{resp, err}
// Wait for the just-returned response body to be fully consumed
// before we race and peek on the underlying bufio reader.
- if alive {
+ if alive && hasBody {
<-resp.Body.(*bodyEOFSignal).ch
}
}
@@ -512,7 +513,7 @@ func responseIsKeepAlive(res *Response) bool {
// the response body with a bodyEOFSignal-wrapped version.
func readResponseWithEOFSignal(r *bufio.Reader, requestMethod string) (resp *Response, err os.Error) {
resp, err = ReadResponse(r, requestMethod)
- if err == nil {
+ if err == nil && resp.ContentLength != 0 {
resp.Body = &bodyEOFSignal{resp.Body, make(chan bool, 1), false}
}
return
diff --git a/src/pkg/http/transport_test.go b/src/pkg/http/transport_test.go
index 69a17df856..6a5438d9c6 100644
--- a/src/pkg/http/transport_test.go
+++ b/src/pkg/http/transport_test.go
@@ -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) {
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
fmt.Fprintf(w, "Hi")