Commit 53493a22 authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

http: don't use ClientConn in Transport

ClientConn's main feature (pipelining support)
wasn't being used anyway.  Ends up simpler to
just not use it.

This is prep for the http diet, moving ClientConn,
ServerConn, etc into http/httputil.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5305088
parent 41dc7d3a
......@@ -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
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment