Home | History | Annotate | Download | only in httputil
      1 // 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 
      5 package httputil
      6 
      7 import (
      8 	"bufio"
      9 	"errors"
     10 	"io"
     11 	"net"
     12 	"net/http"
     13 	"net/textproto"
     14 	"sync"
     15 )
     16 
     17 var (
     18 	ErrPersistEOF = &http.ProtocolError{ErrorString: "persistent connection closed"}
     19 	ErrClosed     = &http.ProtocolError{ErrorString: "connection closed by user"}
     20 	ErrPipeline   = &http.ProtocolError{ErrorString: "pipeline error"}
     21 )
     22 
     23 // This is an API usage error - the local side is closed.
     24 // ErrPersistEOF (above) reports that the remote side is closed.
     25 var errClosed = errors.New("i/o operation on closed connection")
     26 
     27 // A ServerConn reads requests and sends responses over an underlying
     28 // connection, until the HTTP keepalive logic commands an end. ServerConn
     29 // also allows hijacking the underlying connection by calling Hijack
     30 // to regain control over the connection. ServerConn supports pipe-lining,
     31 // i.e. requests can be read out of sync (but in the same order) while the
     32 // respective responses are sent.
     33 //
     34 // ServerConn is low-level and old. Applications should instead use Server
     35 // in the net/http package.
     36 type ServerConn struct {
     37 	lk              sync.Mutex // read-write protects the following fields
     38 	c               net.Conn
     39 	r               *bufio.Reader
     40 	re, we          error // read/write errors
     41 	lastbody        io.ReadCloser
     42 	nread, nwritten int
     43 	pipereq         map[*http.Request]uint
     44 
     45 	pipe textproto.Pipeline
     46 }
     47 
     48 // NewServerConn returns a new ServerConn reading and writing c. If r is not
     49 // nil, it is the buffer to use when reading c.
     50 //
     51 // ServerConn is low-level and old. Applications should instead use Server
     52 // in the net/http package.
     53 func NewServerConn(c net.Conn, r *bufio.Reader) *ServerConn {
     54 	if r == nil {
     55 		r = bufio.NewReader(c)
     56 	}
     57 	return &ServerConn{c: c, r: r, pipereq: make(map[*http.Request]uint)}
     58 }
     59 
     60 // 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
     62 // called before Read has signaled the end of the keep-alive logic. The user
     63 // should not call Hijack while Read or Write is in progress.
     64 func (sc *ServerConn) Hijack() (c net.Conn, r *bufio.Reader) {
     65 	sc.lk.Lock()
     66 	defer sc.lk.Unlock()
     67 	c = sc.c
     68 	r = sc.r
     69 	sc.c = nil
     70 	sc.r = nil
     71 	return
     72 }
     73 
     74 // Close calls Hijack and then also closes the underlying connection
     75 func (sc *ServerConn) Close() error {
     76 	c, _ := sc.Hijack()
     77 	if c != nil {
     78 		return c.Close()
     79 	}
     80 	return nil
     81 }
     82 
     83 // 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
     86 // HTTP/1.1 connection).
     87 func (sc *ServerConn) Read() (req *http.Request, err error) {
     88 
     89 	// 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 
    105 	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 	}
    114 	if sc.r == nil { // connection closed by user in the meantime
    115 		defer sc.lk.Unlock()
    116 		return nil, errClosed
    117 	}
    118 	r := sc.r
    119 	lastbody := sc.lastbody
    120 	sc.lastbody = nil
    121 	sc.lk.Unlock()
    122 
    123 	// Make sure body is fully consumed, even if user does not call body.Close
    124 	if lastbody != nil {
    125 		// body.Close is assumed to be idempotent and multiple calls to
    126 		// it should return the error that its first invocation
    127 		// returned.
    128 		err = lastbody.Close()
    129 		if err != nil {
    130 			sc.lk.Lock()
    131 			defer sc.lk.Unlock()
    132 			sc.re = err
    133 			return nil, err
    134 		}
    135 	}
    136 
    137 	req, err = http.ReadRequest(r)
    138 	sc.lk.Lock()
    139 	defer sc.lk.Unlock()
    140 	if err != nil {
    141 		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
    149 			return req, err
    150 		}
    151 	}
    152 	sc.lastbody = req.Body
    153 	sc.nread++
    154 	if req.Close {
    155 		sc.re = ErrPersistEOF
    156 		return req, sc.re
    157 	}
    158 	return req, err
    159 }
    160 
    161 // Pending returns the number of unanswered requests
    162 // that have been received on the connection.
    163 func (sc *ServerConn) Pending() int {
    164 	sc.lk.Lock()
    165 	defer sc.lk.Unlock()
    166 	return sc.nread - sc.nwritten
    167 }
    168 
    169 // Write writes resp in response to req. To close the connection gracefully, set the
    170 // 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.
    172 func (sc *ServerConn) Write(req *http.Request, resp *http.Response) error {
    173 
    174 	// Retrieve the pipeline ID of this request/response pair
    175 	sc.lk.Lock()
    176 	id, ok := sc.pipereq[req]
    177 	delete(sc.pipereq, req)
    178 	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)
    187 
    188 	sc.lk.Lock()
    189 	if sc.we != nil {
    190 		defer sc.lk.Unlock()
    191 		return sc.we
    192 	}
    193 	if sc.c == nil { // connection closed by user in the meantime
    194 		defer sc.lk.Unlock()
    195 		return ErrClosed
    196 	}
    197 	c := sc.c
    198 	if sc.nread <= sc.nwritten {
    199 		defer sc.lk.Unlock()
    200 		return errors.New("persist server pipe count")
    201 	}
    202 	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.
    206 		sc.re = ErrPersistEOF
    207 	}
    208 	sc.lk.Unlock()
    209 
    210 	err := resp.Write(c)
    211 	sc.lk.Lock()
    212 	defer sc.lk.Unlock()
    213 	if err != nil {
    214 		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
    223 // 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.
    226 //
    227 // ClientConn is low-level and old. Applications should instead use
    228 // Client or Transport in the net/http package.
    229 type ClientConn struct {
    230 	lk              sync.Mutex // read-write protects the following fields
    231 	c               net.Conn
    232 	r               *bufio.Reader
    233 	re, we          error // read/write errors
    234 	lastbody        io.ReadCloser
    235 	nread, nwritten int
    236 	pipereq         map[*http.Request]uint
    237 
    238 	pipe     textproto.Pipeline
    239 	writeReq func(*http.Request, io.Writer) error
    240 }
    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.
    244 //
    245 // ClientConn is low-level and old. Applications should use Client or
    246 // Transport in the net/http package.
    247 func NewClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
    248 	if r == nil {
    249 		r = bufio.NewReader(c)
    250 	}
    251 	return &ClientConn{
    252 		c:        c,
    253 		r:        r,
    254 		pipereq:  make(map[*http.Request]uint),
    255 		writeReq: (*http.Request).Write,
    256 	}
    257 }
    258 
    259 // NewProxyClientConn works like NewClientConn but writes Requests
    260 // using Request's WriteProxy method.
    261 //
    262 // New code should not use NewProxyClientConn. See Client or
    263 // Transport in the net/http package instead.
    264 func NewProxyClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
    265 	cc := NewClientConn(c, r)
    266 	cc.writeReq = (*http.Request).WriteProxy
    267 	return cc
    268 }
    269 
    270 // 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
    272 // called before the user or Read have signaled the end of the keep-alive
    273 // logic. The user should not call Hijack while Read or Write is in progress.
    274 func (cc *ClientConn) Hijack() (c net.Conn, r *bufio.Reader) {
    275 	cc.lk.Lock()
    276 	defer cc.lk.Unlock()
    277 	c = cc.c
    278 	r = cc.r
    279 	cc.c = nil
    280 	cc.r = nil
    281 	return
    282 }
    283 
    284 // Close calls Hijack and then also closes the underlying connection
    285 func (cc *ClientConn) Close() error {
    286 	c, _ := cc.Hijack()
    287 	if c != nil {
    288 		return c.Close()
    289 	}
    290 	return nil
    291 }
    292 
    293 // 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.
    298 func (cc *ClientConn) Write(req *http.Request) (err error) {
    299 
    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 	}()
    315 
    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 	}
    325 	if cc.c == nil { // connection closed by user in the meantime
    326 		defer cc.lk.Unlock()
    327 		return errClosed
    328 	}
    329 	c := cc.c
    330 	if req.Close {
    331 		// We write the EOF to the write-side error, because there
    332 		// still might be some pipelined reads
    333 		cc.we = ErrPersistEOF
    334 	}
    335 	cc.lk.Unlock()
    336 
    337 	err = cc.writeReq(req, c)
    338 	cc.lk.Lock()
    339 	defer cc.lk.Unlock()
    340 	if err != nil {
    341 		cc.we = err
    342 		return err
    343 	}
    344 	cc.nwritten++
    345 
    346 	return nil
    347 }
    348 
    349 // Pending returns the number of unanswered requests
    350 // that have been sent on the connection.
    351 func (cc *ClientConn) Pending() int {
    352 	cc.lk.Lock()
    353 	defer cc.lk.Unlock()
    354 	return cc.nwritten - cc.nread
    355 }
    356 
    357 // 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.
    361 func (cc *ClientConn) Read(req *http.Request) (resp *http.Response, err error) {
    362 	// Retrieve the pipeline ID of this request/response pair
    363 	cc.lk.Lock()
    364 	id, ok := cc.pipereq[req]
    365 	delete(cc.pipereq, req)
    366 	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)
    375 
    376 	cc.lk.Lock()
    377 	if cc.re != nil {
    378 		defer cc.lk.Unlock()
    379 		return nil, cc.re
    380 	}
    381 	if cc.r == nil { // connection closed by user in the meantime
    382 		defer cc.lk.Unlock()
    383 		return nil, errClosed
    384 	}
    385 	r := cc.r
    386 	lastbody := cc.lastbody
    387 	cc.lastbody = nil
    388 	cc.lk.Unlock()
    389 
    390 	// Make sure body is fully consumed, even if user does not call body.Close
    391 	if lastbody != nil {
    392 		// body.Close is assumed to be idempotent and multiple calls to
    393 		// it should return the error that its first invocation
    394 		// returned.
    395 		err = lastbody.Close()
    396 		if err != nil {
    397 			cc.lk.Lock()
    398 			defer cc.lk.Unlock()
    399 			cc.re = err
    400 			return nil, err
    401 		}
    402 	}
    403 
    404 	resp, err = http.ReadResponse(r, req)
    405 	cc.lk.Lock()
    406 	defer cc.lk.Unlock()
    407 	if err != nil {
    408 		cc.re = err
    409 		return resp, err
    410 	}
    411 	cc.lastbody = resp.Body
    412 
    413 	cc.nread++
    414 
    415 	if resp.Close {
    416 		cc.re = ErrPersistEOF // don't send any more requests
    417 		return resp, cc.re
    418 	}
    419 	return resp, err
    420 }
    421 
    422 // Do is convenience method that writes a request and reads a response.
    423 func (cc *ClientConn) Do(req *http.Request) (resp *http.Response, err error) {
    424 	err = cc.Write(req)
    425 	if err != nil {
    426 		return
    427 	}
    428 	return cc.Read(req)
    429 }
    430