diff options
Diffstat (limited to 'src/pkg/http')
| -rw-r--r-- | src/pkg/http/transport.go | 54 |
1 files changed, 25 insertions, 29 deletions
diff --git a/src/pkg/http/transport.go b/src/pkg/http/transport.go index c7041cba2e..5e167fef8e 100644 --- a/src/pkg/http/transport.go +++ b/src/pkg/http/transport.go @@ -372,7 +372,7 @@ func (t *Transport) getConn(cm *connectMethod) (*persistConn, error) { } pconn.br = bufio.NewReader(pconn.conn) - pconn.cc = NewClientConn(conn, pconn.br) + pconn.bw = bufio.NewWriter(pconn.conn) go pconn.readLoop() return pconn, nil } @@ -474,8 +474,8 @@ type persistConn struct { t *Transport cacheKey string // its connectMethod.String() conn net.Conn - cc *ClientConn - br *bufio.Reader + br *bufio.Reader // from conn + bw *bufio.Writer // to conn reqch chan requestAndChan // written by roundTrip(); read by readLoop() isProxy bool @@ -515,6 +515,8 @@ func remoteSideClosed(err error) bool { func (pc *persistConn) readLoop() { alive := true + var lastbody io.ReadCloser // last response body, if any, read on this connection + for alive { pb, err := pc.br.Peek(1) if err != nil { @@ -533,33 +535,32 @@ func (pc *persistConn) readLoop() { } rc := <-pc.reqch - resp, err := pc.cc.readUsing(rc.req, func(buf *bufio.Reader, forReq *Request) (*Response, error) { - resp, err := ReadResponse(buf, forReq) - if err != nil || resp.ContentLength == 0 { - return resp, err - } + + // Advance past the previous response's body, if the + // caller hasn't done so. + if lastbody != nil { + lastbody.Close() // assumed idempotent + lastbody = nil + } + resp, err := ReadResponse(pc.br, rc.req) + + if err == nil { if rc.addedGzip && resp.Header.Get("Content-Encoding") == "gzip" { resp.Header.Del("Content-Encoding") resp.Header.Del("Content-Length") resp.ContentLength = -1 - gzReader, err := gzip.NewReader(resp.Body) + gzReader, zerr := gzip.NewReader(resp.Body) if err != nil { pc.close() - return nil, err + err = zerr + } else { + resp.Body = &readFirstCloseBoth{&discardOnCloseReadCloser{gzReader}, resp.Body} } - resp.Body = &readFirstCloseBoth{&discardOnCloseReadCloser{gzReader}, resp.Body} } resp.Body = &bodyEOFSignal{body: resp.Body} - return resp, err - }) + } - if err == ErrPersistEOF { - // Succeeded, but we can't send any more - // persistent connections on this again. We - // hide this error to upstream callers. - alive = false - err = nil - } else if err != nil || rc.req.Close { + if err != nil || resp.Close || rc.req.Close { alive = false } @@ -567,6 +568,7 @@ func (pc *persistConn) readLoop() { var waitForBodyRead chan bool if alive { if hasBody { + lastbody = resp.Body waitForBodyRead = make(chan bool) resp.Body.(*bodyEOFSignal).fn = func() { pc.t.putIdleConn(pc) @@ -580,9 +582,7 @@ func (pc *persistConn) readLoop() { // loop, otherwise it might close the body // before the client code has had a chance to // read it (even though it'll just be 0, EOF). - pc.cc.lk.Lock() - pc.cc.lastbody = nil - pc.cc.lk.Unlock() + lastbody = nil pc.t.putIdleConn(pc) } @@ -635,15 +635,12 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err pc.numExpectedResponses++ pc.lk.Unlock() - pc.cc.writeReq = func(r *Request, w io.Writer) error { - return r.write(w, pc.isProxy, req.extra) - } - - err = pc.cc.Write(req.Request) + err = req.Request.write(pc.bw, pc.isProxy, req.extra) if err != nil { pc.close() return } + pc.bw.Flush() ch := make(chan responseAndError, 1) pc.reqch <- requestAndChan{req.Request, ch, requestedGzip} @@ -659,7 +656,6 @@ func (pc *persistConn) close() { pc.lk.Lock() defer pc.lk.Unlock() pc.broken = true - pc.cc.Close() pc.conn.Close() pc.mutateHeaderFunc = nil } |
