blob: 987bcc96ba1d16c8dd26ffd3296f287c1ddb1c74 [file] [log] [blame]
Petar Maymounkovd26e2042010-02-18 23:38:21 -08001// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Brad Fitzpatricka7f11412011-11-03 14:44:29 -07005package httputil
Petar Maymounkovd26e2042010-02-18 23:38:21 -08006
7import (
8 "bufio"
Russ Coxc2049d22011-11-01 22:04:37 -04009 "errors"
Petar Maymounkovd26e2042010-02-18 23:38:21 -080010 "io"
11 "net"
Rob Pike45e3bcb2011-11-08 15:41:54 -080012 "net/http"
Petar Maymounkov3de98462011-02-11 15:05:47 -050013 "net/textproto"
Petar Maymounkovd26e2042010-02-18 23:38:21 -080014 "sync"
15)
16
Petar Maymounkov3de98462011-02-11 15:05:47 -050017var (
Nigel Tao102638c2012-02-03 10:12:25 +110018 ErrPersistEOF = &http.ProtocolError{ErrorString: "persistent connection closed"}
Rob Pike56069f02012-02-17 10:04:29 +110019 ErrClosed = &http.ProtocolError{ErrorString: "connection closed by user"}
Nigel Tao102638c2012-02-03 10:12:25 +110020 ErrPipeline = &http.ProtocolError{ErrorString: "pipeline error"}
Petar Maymounkov3de98462011-02-11 15:05:47 -050021)
Petar Maymounkovd26e2042010-02-18 23:38:21 -080022
Russ Coxfd34e782011-11-13 22:42:42 -050023// This is an API usage error - the local side is closed.
24// ErrPersistEOF (above) reports that the remote side is closed.
25var errClosed = errors.New("i/o operation on closed connection")
26
Petar Maymounkovd26e2042010-02-18 23:38:21 -080027// A ServerConn reads requests and sends responses over an underlying
28// connection, until the HTTP keepalive logic commands an end. ServerConn
Petar Maymounkovf5897282011-04-22 15:56:27 -040029// also allows hijacking the underlying connection by calling Hijack
30// to regain control over the connection. ServerConn supports pipe-lining,
Petar Maymounkovd26e2042010-02-18 23:38:21 -080031// i.e. requests can be read out of sync (but in the same order) while the
32// respective responses are sent.
Brad Fitzpatrickd980f532011-06-29 18:23:38 -070033//
Brad Fitzpatrick9f2e1ef2014-04-26 22:14:39 -070034// ServerConn is low-level and old. Applications should instead use Server
35// in the net/http package.
Petar Maymounkovd26e2042010-02-18 23:38:21 -080036type ServerConn struct {
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -050037 lk sync.Mutex // read-write protects the following fields
Petar Maymounkovd26e2042010-02-18 23:38:21 -080038 c net.Conn
39 r *bufio.Reader
Russ Coxc2049d22011-11-01 22:04:37 -040040 re, we error // read/write errors
Petar Maymounkov3de98462011-02-11 15:05:47 -050041 lastbody io.ReadCloser
Petar Maymounkovd26e2042010-02-18 23:38:21 -080042 nread, nwritten int
Brad Fitzpatricka7f11412011-11-03 14:44:29 -070043 pipereq map[*http.Request]uint
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -050044
45 pipe textproto.Pipeline
Petar Maymounkovd26e2042010-02-18 23:38:21 -080046}
47
Brad Fitzpatrick9f2e1ef2014-04-26 22:14:39 -070048// NewServerConn returns a new ServerConn reading and writing c. If r is not
Petar Maymounkovd26e2042010-02-18 23:38:21 -080049// nil, it is the buffer to use when reading c.
Brad Fitzpatrick9f2e1ef2014-04-26 22:14:39 -070050//
51// ServerConn is low-level and old. Applications should instead use Server
52// in the net/http package.
Petar Maymounkovd26e2042010-02-18 23:38:21 -080053func NewServerConn(c net.Conn, r *bufio.Reader) *ServerConn {
54 if r == nil {
55 r = bufio.NewReader(c)
56 }
Brad Fitzpatricka7f11412011-11-03 14:44:29 -070057 return &ServerConn{c: c, r: r, pipereq: make(map[*http.Request]uint)}
Petar Maymounkovd26e2042010-02-18 23:38:21 -080058}
59
Petar Maymounkovf5897282011-04-22 15:56:27 -040060// Hijack detaches the ServerConn and returns the underlying connection as well
61// as the read-side bufio which may have some left over data. Hijack may be
Petar Maymounkovd26e2042010-02-18 23:38:21 -080062// called before Read has signaled the end of the keep-alive logic. The user
Petar Maymounkovf5897282011-04-22 15:56:27 -040063// should not call Hijack while Read or Write is in progress.
64func (sc *ServerConn) Hijack() (c net.Conn, r *bufio.Reader) {
Petar Maymounkov8d9c2b22010-02-19 08:21:21 -080065 sc.lk.Lock()
66 defer sc.lk.Unlock()
Petar Maymounkovd26e2042010-02-18 23:38:21 -080067 c = sc.c
68 r = sc.r
69 sc.c = nil
70 sc.r = nil
71 return
72}
73
Petar Maymounkovf5897282011-04-22 15:56:27 -040074// Close calls Hijack and then also closes the underlying connection
Russ Coxc2049d22011-11-01 22:04:37 -040075func (sc *ServerConn) Close() error {
Petar Maymounkovf5897282011-04-22 15:56:27 -040076 c, _ := sc.Hijack()
77 if c != nil {
78 return c.Close()
79 }
80 return nil
81}
82
Petar Maymounkovd26e2042010-02-18 23:38:21 -080083// Read returns the next request on the wire. An ErrPersistEOF is returned if
84// it is gracefully determined that there are no more requests (e.g. after the
85// first request on an HTTP/1.0 connection, or after a Connection:close on a
Petar Maymounkov3de98462011-02-11 15:05:47 -050086// HTTP/1.1 connection).
Brad Fitzpatricka7f11412011-11-03 14:44:29 -070087func (sc *ServerConn) Read() (req *http.Request, err error) {
Petar Maymounkovd26e2042010-02-18 23:38:21 -080088
Petar Maymounkov3de98462011-02-11 15:05:47 -050089 // Ensure ordered execution of Reads and Writes
90 id := sc.pipe.Next()
91 sc.pipe.StartRequest(id)
92 defer func() {
93 sc.pipe.EndRequest(id)
94 if req == nil {
95 sc.pipe.StartResponse(id)
96 sc.pipe.EndResponse(id)
97 } else {
98 // Remember the pipeline id of this request
99 sc.lk.Lock()
100 sc.pipereq[req] = id
101 sc.lk.Unlock()
102 }
103 }()
104
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800105 sc.lk.Lock()
106 if sc.we != nil { // no point receiving if write-side broken or closed
107 defer sc.lk.Unlock()
108 return nil, sc.we
109 }
110 if sc.re != nil {
111 defer sc.lk.Unlock()
112 return nil, sc.re
113 }
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500114 if sc.r == nil { // connection closed by user in the meantime
115 defer sc.lk.Unlock()
Russ Coxfd34e782011-11-13 22:42:42 -0500116 return nil, errClosed
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500117 }
118 r := sc.r
119 lastbody := sc.lastbody
120 sc.lastbody = nil
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800121 sc.lk.Unlock()
122
123 // Make sure body is fully consumed, even if user does not call body.Close
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500124 if lastbody != nil {
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800125 // body.Close is assumed to be idempotent and multiple calls to
Robert Henckec8727c82011-05-18 13:14:56 -0400126 // it should return the error that its first invocation
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800127 // returned.
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500128 err = lastbody.Close()
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800129 if err != nil {
130 sc.lk.Lock()
131 defer sc.lk.Unlock()
132 sc.re = err
133 return nil, err
134 }
135 }
136
Brad Fitzpatricka7f11412011-11-03 14:44:29 -0700137 req, err = http.ReadRequest(r)
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500138 sc.lk.Lock()
139 defer sc.lk.Unlock()
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800140 if err != nil {
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800141 if err == io.ErrUnexpectedEOF {
142 // A close from the opposing client is treated as a
143 // graceful close, even if there was some unparse-able
144 // data before the close.
145 sc.re = ErrPersistEOF
146 return nil, sc.re
147 } else {
148 sc.re = err
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500149 return req, err
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800150 }
151 }
Petar Maymounkov3de98462011-02-11 15:05:47 -0500152 sc.lastbody = req.Body
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800153 sc.nread++
154 if req.Close {
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800155 sc.re = ErrPersistEOF
156 return req, sc.re
157 }
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500158 return req, err
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800159}
160
Petar Maymounkov8d9c2b22010-02-19 08:21:21 -0800161// Pending returns the number of unanswered requests
162// that have been received on the connection.
163func (sc *ServerConn) Pending() int {
164 sc.lk.Lock()
165 defer sc.lk.Unlock()
166 return sc.nread - sc.nwritten
167}
168
Petar Maymounkov3de98462011-02-11 15:05:47 -0500169// Write writes resp in response to req. To close the connection gracefully, set the
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800170// Response.Close field to true. Write should be considered operational until
171// it returns an error, regardless of any errors returned on the Read side.
Brad Fitzpatricka7f11412011-11-03 14:44:29 -0700172func (sc *ServerConn) Write(req *http.Request, resp *http.Response) error {
Petar Maymounkov3de98462011-02-11 15:05:47 -0500173
174 // Retrieve the pipeline ID of this request/response pair
175 sc.lk.Lock()
176 id, ok := sc.pipereq[req]
Russ Cox313c8222011-10-18 09:56:34 -0400177 delete(sc.pipereq, req)
Petar Maymounkov3de98462011-02-11 15:05:47 -0500178 if !ok {
179 sc.lk.Unlock()
180 return ErrPipeline
181 }
182 sc.lk.Unlock()
183
184 // Ensure pipeline order
185 sc.pipe.StartResponse(id)
186 defer sc.pipe.EndResponse(id)
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800187
188 sc.lk.Lock()
189 if sc.we != nil {
190 defer sc.lk.Unlock()
191 return sc.we
192 }
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500193 if sc.c == nil { // connection closed by user in the meantime
194 defer sc.lk.Unlock()
Rob Pike56069f02012-02-17 10:04:29 +1100195 return ErrClosed
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500196 }
197 c := sc.c
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800198 if sc.nread <= sc.nwritten {
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500199 defer sc.lk.Unlock()
Russ Coxc2049d22011-11-01 22:04:37 -0400200 return errors.New("persist server pipe count")
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800201 }
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800202 if resp.Close {
203 // After signaling a keep-alive close, any pipelined unread
204 // requests will be lost. It is up to the user to drain them
205 // before signaling.
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800206 sc.re = ErrPersistEOF
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800207 }
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500208 sc.lk.Unlock()
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800209
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500210 err := resp.Write(c)
211 sc.lk.Lock()
212 defer sc.lk.Unlock()
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800213 if err != nil {
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800214 sc.we = err
215 return err
216 }
217 sc.nwritten++
218
219 return nil
220}
221
222// A ClientConn sends request and receives headers over an underlying
Petar Maymounkovf5897282011-04-22 15:56:27 -0400223// connection, while respecting the HTTP keepalive logic. ClientConn
224// supports hijacking the connection calling Hijack to
225// regain control of the underlying net.Conn and deal with it as desired.
Brad Fitzpatrickd980f532011-06-29 18:23:38 -0700226//
Brad Fitzpatrick9f2e1ef2014-04-26 22:14:39 -0700227// ClientConn is low-level and old. Applications should instead use
228// Client or Transport in the net/http package.
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800229type ClientConn struct {
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500230 lk sync.Mutex // read-write protects the following fields
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800231 c net.Conn
232 r *bufio.Reader
Russ Coxc2049d22011-11-01 22:04:37 -0400233 re, we error // read/write errors
Petar Maymounkov3de98462011-02-11 15:05:47 -0500234 lastbody io.ReadCloser
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800235 nread, nwritten int
Brad Fitzpatricka7f11412011-11-03 14:44:29 -0700236 pipereq map[*http.Request]uint
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500237
Brad Fitzpatricka93f70c2011-03-16 14:32:35 -0700238 pipe textproto.Pipeline
Brad Fitzpatricka7f11412011-11-03 14:44:29 -0700239 writeReq func(*http.Request, io.Writer) error
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800240}
241
242// NewClientConn returns a new ClientConn reading and writing c. If r is not
243// nil, it is the buffer to use when reading c.
Brad Fitzpatrick9f2e1ef2014-04-26 22:14:39 -0700244//
245// ClientConn is low-level and old. Applications should use Client or
246// Transport in the net/http package.
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800247func NewClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
248 if r == nil {
249 r = bufio.NewReader(c)
250 }
Brad Fitzpatricka93f70c2011-03-16 14:32:35 -0700251 return &ClientConn{
252 c: c,
253 r: r,
Brad Fitzpatricka7f11412011-11-03 14:44:29 -0700254 pipereq: make(map[*http.Request]uint),
255 writeReq: (*http.Request).Write,
Brad Fitzpatricka93f70c2011-03-16 14:32:35 -0700256 }
257}
258
259// NewProxyClientConn works like NewClientConn but writes Requests
260// using Request's WriteProxy method.
Brad Fitzpatrick9f2e1ef2014-04-26 22:14:39 -0700261//
262// New code should not use NewProxyClientConn. See Client or
263// Transport in the net/http package instead.
Brad Fitzpatricka93f70c2011-03-16 14:32:35 -0700264func NewProxyClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
265 cc := NewClientConn(c, r)
Brad Fitzpatricka7f11412011-11-03 14:44:29 -0700266 cc.writeReq = (*http.Request).WriteProxy
Brad Fitzpatricka93f70c2011-03-16 14:32:35 -0700267 return cc
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800268}
269
Petar Maymounkovf5897282011-04-22 15:56:27 -0400270// Hijack detaches the ClientConn and returns the underlying connection as well
271// as the read-side bufio which may have some left over data. Hijack may be
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800272// called before the user or Read have signaled the end of the keep-alive
Petar Maymounkovf5897282011-04-22 15:56:27 -0400273// logic. The user should not call Hijack while Read or Write is in progress.
274func (cc *ClientConn) Hijack() (c net.Conn, r *bufio.Reader) {
Petar Maymounkov8d9c2b22010-02-19 08:21:21 -0800275 cc.lk.Lock()
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500276 defer cc.lk.Unlock()
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800277 c = cc.c
278 r = cc.r
279 cc.c = nil
280 cc.r = nil
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800281 return
282}
283
Petar Maymounkovf5897282011-04-22 15:56:27 -0400284// Close calls Hijack and then also closes the underlying connection
Russ Coxc2049d22011-11-01 22:04:37 -0400285func (cc *ClientConn) Close() error {
Petar Maymounkovf5897282011-04-22 15:56:27 -0400286 c, _ := cc.Hijack()
287 if c != nil {
288 return c.Close()
289 }
290 return nil
291}
292
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800293// Write writes a request. An ErrPersistEOF error is returned if the connection
294// has been closed in an HTTP keepalive sense. If req.Close equals true, the
295// keepalive connection is logically closed after this request and the opposing
296// server is informed. An ErrUnexpectedEOF indicates the remote closed the
297// underlying TCP connection, which is usually considered as graceful close.
Brad Fitzpatricka7f11412011-11-03 14:44:29 -0700298func (cc *ClientConn) Write(req *http.Request) (err error) {
Petar Maymounkov3de98462011-02-11 15:05:47 -0500299
300 // Ensure ordered execution of Writes
301 id := cc.pipe.Next()
302 cc.pipe.StartRequest(id)
303 defer func() {
304 cc.pipe.EndRequest(id)
305 if err != nil {
306 cc.pipe.StartResponse(id)
307 cc.pipe.EndResponse(id)
308 } else {
309 // Remember the pipeline id of this request
310 cc.lk.Lock()
311 cc.pipereq[req] = id
312 cc.lk.Unlock()
313 }
314 }()
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800315
316 cc.lk.Lock()
317 if cc.re != nil { // no point sending if read-side closed or broken
318 defer cc.lk.Unlock()
319 return cc.re
320 }
321 if cc.we != nil {
322 defer cc.lk.Unlock()
323 return cc.we
324 }
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500325 if cc.c == nil { // connection closed by user in the meantime
326 defer cc.lk.Unlock()
Russ Coxfd34e782011-11-13 22:42:42 -0500327 return errClosed
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500328 }
329 c := cc.c
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800330 if req.Close {
331 // We write the EOF to the write-side error, because there
332 // still might be some pipelined reads
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800333 cc.we = ErrPersistEOF
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800334 }
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500335 cc.lk.Unlock()
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800336
Brad Fitzpatricka93f70c2011-03-16 14:32:35 -0700337 err = cc.writeReq(req, c)
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500338 cc.lk.Lock()
339 defer cc.lk.Unlock()
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800340 if err != nil {
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800341 cc.we = err
342 return err
343 }
344 cc.nwritten++
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800345
346 return nil
347}
348
Petar Maymounkov8d9c2b22010-02-19 08:21:21 -0800349// Pending returns the number of unanswered requests
350// that have been sent on the connection.
351func (cc *ClientConn) Pending() int {
352 cc.lk.Lock()
353 defer cc.lk.Unlock()
354 return cc.nwritten - cc.nread
355}
356
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800357// Read reads the next response from the wire. A valid response might be
358// returned together with an ErrPersistEOF, which means that the remote
359// requested that this be the last request serviced. Read can be called
360// concurrently with Write, but not with another Read.
Brad Fitzpatricka7f11412011-11-03 14:44:29 -0700361func (cc *ClientConn) Read(req *http.Request) (resp *http.Response, err error) {
Petar Maymounkov3de98462011-02-11 15:05:47 -0500362 // Retrieve the pipeline ID of this request/response pair
363 cc.lk.Lock()
364 id, ok := cc.pipereq[req]
Russ Cox313c8222011-10-18 09:56:34 -0400365 delete(cc.pipereq, req)
Petar Maymounkov3de98462011-02-11 15:05:47 -0500366 if !ok {
367 cc.lk.Unlock()
368 return nil, ErrPipeline
369 }
370 cc.lk.Unlock()
371
372 // Ensure pipeline order
373 cc.pipe.StartResponse(id)
374 defer cc.pipe.EndResponse(id)
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800375
376 cc.lk.Lock()
377 if cc.re != nil {
378 defer cc.lk.Unlock()
379 return nil, cc.re
380 }
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500381 if cc.r == nil { // connection closed by user in the meantime
382 defer cc.lk.Unlock()
Russ Coxfd34e782011-11-13 22:42:42 -0500383 return nil, errClosed
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500384 }
385 r := cc.r
386 lastbody := cc.lastbody
387 cc.lastbody = nil
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800388 cc.lk.Unlock()
389
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800390 // Make sure body is fully consumed, even if user does not call body.Close
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500391 if lastbody != nil {
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800392 // body.Close is assumed to be idempotent and multiple calls to
Robert Griesemer7c6654a2012-03-01 14:56:05 -0800393 // it should return the error that its first invocation
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800394 // returned.
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500395 err = lastbody.Close()
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800396 if err != nil {
397 cc.lk.Lock()
398 defer cc.lk.Unlock()
399 cc.re = err
400 return nil, err
401 }
402 }
403
Brad Fitzpatricka7f11412011-11-03 14:44:29 -0700404 resp, err = http.ReadResponse(r, req)
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500405 cc.lk.Lock()
406 defer cc.lk.Unlock()
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800407 if err != nil {
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800408 cc.re = err
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500409 return resp, err
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800410 }
Petar Maymounkov3de98462011-02-11 15:05:47 -0500411 cc.lastbody = resp.Body
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800412
413 cc.nread++
414
415 if resp.Close {
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800416 cc.re = ErrPersistEOF // don't send any more requests
417 return resp, cc.re
418 }
Petar Maymounkov5db0a8b2011-03-05 14:44:05 -0500419 return resp, err
Petar Maymounkovd26e2042010-02-18 23:38:21 -0800420}
Petar Maymounkov3de98462011-02-11 15:05:47 -0500421
422// Do is convenience method that writes a request and reads a response.
Brad Fitzpatricka7f11412011-11-03 14:44:29 -0700423func (cc *ClientConn) Do(req *http.Request) (resp *http.Response, err error) {
Petar Maymounkov3de98462011-02-11 15:05:47 -0500424 err = cc.Write(req)
425 if err != nil {
426 return
427 }
428 return cc.Read(req)
429}