github.com/gocuntian/go@v0.0.0-20160610041250-fee02d270bf8/src/net/http/httputil/persist.go (about) 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 // ServerConn is an artifact of Go's early HTTP implementation. 28 // It is low-level, old, and unused by Go's current HTTP stack. 29 // We should have deleted it before Go 1. 30 // 31 // Deprecated: Use the Server in package net/http instead. 32 type ServerConn struct { 33 mu sync.Mutex // read-write protects the following fields 34 c net.Conn 35 r *bufio.Reader 36 re, we error // read/write errors 37 lastbody io.ReadCloser 38 nread, nwritten int 39 pipereq map[*http.Request]uint 40 41 pipe textproto.Pipeline 42 } 43 44 // NewServerConn is an artifact of Go's early HTTP implementation. 45 // It is low-level, old, and unused by Go's current HTTP stack. 46 // We should have deleted it before Go 1. 47 // 48 // Deprecated: Use the Server in package net/http instead. 49 func NewServerConn(c net.Conn, r *bufio.Reader) *ServerConn { 50 if r == nil { 51 r = bufio.NewReader(c) 52 } 53 return &ServerConn{c: c, r: r, pipereq: make(map[*http.Request]uint)} 54 } 55 56 // Hijack detaches the ServerConn and returns the underlying connection as well 57 // as the read-side bufio which may have some left over data. Hijack may be 58 // called before Read has signaled the end of the keep-alive logic. The user 59 // should not call Hijack while Read or Write is in progress. 60 func (sc *ServerConn) Hijack() (net.Conn, *bufio.Reader) { 61 sc.mu.Lock() 62 defer sc.mu.Unlock() 63 c := sc.c 64 r := sc.r 65 sc.c = nil 66 sc.r = nil 67 return c, r 68 } 69 70 // Close calls Hijack and then also closes the underlying connection. 71 func (sc *ServerConn) Close() error { 72 c, _ := sc.Hijack() 73 if c != nil { 74 return c.Close() 75 } 76 return nil 77 } 78 79 // Read returns the next request on the wire. An ErrPersistEOF is returned if 80 // it is gracefully determined that there are no more requests (e.g. after the 81 // first request on an HTTP/1.0 connection, or after a Connection:close on a 82 // HTTP/1.1 connection). 83 func (sc *ServerConn) Read() (*http.Request, error) { 84 var req *http.Request 85 var err error 86 87 // Ensure ordered execution of Reads and Writes 88 id := sc.pipe.Next() 89 sc.pipe.StartRequest(id) 90 defer func() { 91 sc.pipe.EndRequest(id) 92 if req == nil { 93 sc.pipe.StartResponse(id) 94 sc.pipe.EndResponse(id) 95 } else { 96 // Remember the pipeline id of this request 97 sc.mu.Lock() 98 sc.pipereq[req] = id 99 sc.mu.Unlock() 100 } 101 }() 102 103 sc.mu.Lock() 104 if sc.we != nil { // no point receiving if write-side broken or closed 105 defer sc.mu.Unlock() 106 return nil, sc.we 107 } 108 if sc.re != nil { 109 defer sc.mu.Unlock() 110 return nil, sc.re 111 } 112 if sc.r == nil { // connection closed by user in the meantime 113 defer sc.mu.Unlock() 114 return nil, errClosed 115 } 116 r := sc.r 117 lastbody := sc.lastbody 118 sc.lastbody = nil 119 sc.mu.Unlock() 120 121 // Make sure body is fully consumed, even if user does not call body.Close 122 if lastbody != nil { 123 // body.Close is assumed to be idempotent and multiple calls to 124 // it should return the error that its first invocation 125 // returned. 126 err = lastbody.Close() 127 if err != nil { 128 sc.mu.Lock() 129 defer sc.mu.Unlock() 130 sc.re = err 131 return nil, err 132 } 133 } 134 135 req, err = http.ReadRequest(r) 136 sc.mu.Lock() 137 defer sc.mu.Unlock() 138 if err != nil { 139 if err == io.ErrUnexpectedEOF { 140 // A close from the opposing client is treated as a 141 // graceful close, even if there was some unparse-able 142 // data before the close. 143 sc.re = ErrPersistEOF 144 return nil, sc.re 145 } else { 146 sc.re = err 147 return req, err 148 } 149 } 150 sc.lastbody = req.Body 151 sc.nread++ 152 if req.Close { 153 sc.re = ErrPersistEOF 154 return req, sc.re 155 } 156 return req, err 157 } 158 159 // Pending returns the number of unanswered requests 160 // that have been received on the connection. 161 func (sc *ServerConn) Pending() int { 162 sc.mu.Lock() 163 defer sc.mu.Unlock() 164 return sc.nread - sc.nwritten 165 } 166 167 // Write writes resp in response to req. To close the connection gracefully, set the 168 // Response.Close field to true. Write should be considered operational until 169 // it returns an error, regardless of any errors returned on the Read side. 170 func (sc *ServerConn) Write(req *http.Request, resp *http.Response) error { 171 172 // Retrieve the pipeline ID of this request/response pair 173 sc.mu.Lock() 174 id, ok := sc.pipereq[req] 175 delete(sc.pipereq, req) 176 if !ok { 177 sc.mu.Unlock() 178 return ErrPipeline 179 } 180 sc.mu.Unlock() 181 182 // Ensure pipeline order 183 sc.pipe.StartResponse(id) 184 defer sc.pipe.EndResponse(id) 185 186 sc.mu.Lock() 187 if sc.we != nil { 188 defer sc.mu.Unlock() 189 return sc.we 190 } 191 if sc.c == nil { // connection closed by user in the meantime 192 defer sc.mu.Unlock() 193 return ErrClosed 194 } 195 c := sc.c 196 if sc.nread <= sc.nwritten { 197 defer sc.mu.Unlock() 198 return errors.New("persist server pipe count") 199 } 200 if resp.Close { 201 // After signaling a keep-alive close, any pipelined unread 202 // requests will be lost. It is up to the user to drain them 203 // before signaling. 204 sc.re = ErrPersistEOF 205 } 206 sc.mu.Unlock() 207 208 err := resp.Write(c) 209 sc.mu.Lock() 210 defer sc.mu.Unlock() 211 if err != nil { 212 sc.we = err 213 return err 214 } 215 sc.nwritten++ 216 217 return nil 218 } 219 220 // ClientConn is an artifact of Go's early HTTP implementation. 221 // It is low-level, old, and unused by Go's current HTTP stack. 222 // We should have deleted it before Go 1. 223 // 224 // Deprecated: Use Client or Transport in package net/http instead. 225 type ClientConn struct { 226 mu sync.Mutex // read-write protects the following fields 227 c net.Conn 228 r *bufio.Reader 229 re, we error // read/write errors 230 lastbody io.ReadCloser 231 nread, nwritten int 232 pipereq map[*http.Request]uint 233 234 pipe textproto.Pipeline 235 writeReq func(*http.Request, io.Writer) error 236 } 237 238 // NewClientConn is an artifact of Go's early HTTP implementation. 239 // It is low-level, old, and unused by Go's current HTTP stack. 240 // We should have deleted it before Go 1. 241 // 242 // Deprecated: Use the Client or Transport in package net/http instead. 243 func NewClientConn(c net.Conn, r *bufio.Reader) *ClientConn { 244 if r == nil { 245 r = bufio.NewReader(c) 246 } 247 return &ClientConn{ 248 c: c, 249 r: r, 250 pipereq: make(map[*http.Request]uint), 251 writeReq: (*http.Request).Write, 252 } 253 } 254 255 // NewProxyClientConn is an artifact of Go's early HTTP implementation. 256 // It is low-level, old, and unused by Go's current HTTP stack. 257 // We should have deleted it before Go 1. 258 // 259 // Deprecated: Use the Client or Transport in package net/http instead. 260 func NewProxyClientConn(c net.Conn, r *bufio.Reader) *ClientConn { 261 cc := NewClientConn(c, r) 262 cc.writeReq = (*http.Request).WriteProxy 263 return cc 264 } 265 266 // Hijack detaches the ClientConn and returns the underlying connection as well 267 // as the read-side bufio which may have some left over data. Hijack may be 268 // called before the user or Read have signaled the end of the keep-alive 269 // logic. The user should not call Hijack while Read or Write is in progress. 270 func (cc *ClientConn) Hijack() (c net.Conn, r *bufio.Reader) { 271 cc.mu.Lock() 272 defer cc.mu.Unlock() 273 c = cc.c 274 r = cc.r 275 cc.c = nil 276 cc.r = nil 277 return 278 } 279 280 // Close calls Hijack and then also closes the underlying connection. 281 func (cc *ClientConn) Close() error { 282 c, _ := cc.Hijack() 283 if c != nil { 284 return c.Close() 285 } 286 return nil 287 } 288 289 // Write writes a request. An ErrPersistEOF error is returned if the connection 290 // has been closed in an HTTP keepalive sense. If req.Close equals true, the 291 // keepalive connection is logically closed after this request and the opposing 292 // server is informed. An ErrUnexpectedEOF indicates the remote closed the 293 // underlying TCP connection, which is usually considered as graceful close. 294 func (cc *ClientConn) Write(req *http.Request) error { 295 var err error 296 297 // Ensure ordered execution of Writes 298 id := cc.pipe.Next() 299 cc.pipe.StartRequest(id) 300 defer func() { 301 cc.pipe.EndRequest(id) 302 if err != nil { 303 cc.pipe.StartResponse(id) 304 cc.pipe.EndResponse(id) 305 } else { 306 // Remember the pipeline id of this request 307 cc.mu.Lock() 308 cc.pipereq[req] = id 309 cc.mu.Unlock() 310 } 311 }() 312 313 cc.mu.Lock() 314 if cc.re != nil { // no point sending if read-side closed or broken 315 defer cc.mu.Unlock() 316 return cc.re 317 } 318 if cc.we != nil { 319 defer cc.mu.Unlock() 320 return cc.we 321 } 322 if cc.c == nil { // connection closed by user in the meantime 323 defer cc.mu.Unlock() 324 return errClosed 325 } 326 c := cc.c 327 if req.Close { 328 // We write the EOF to the write-side error, because there 329 // still might be some pipelined reads 330 cc.we = ErrPersistEOF 331 } 332 cc.mu.Unlock() 333 334 err = cc.writeReq(req, c) 335 cc.mu.Lock() 336 defer cc.mu.Unlock() 337 if err != nil { 338 cc.we = err 339 return err 340 } 341 cc.nwritten++ 342 343 return nil 344 } 345 346 // Pending returns the number of unanswered requests 347 // that have been sent on the connection. 348 func (cc *ClientConn) Pending() int { 349 cc.mu.Lock() 350 defer cc.mu.Unlock() 351 return cc.nwritten - cc.nread 352 } 353 354 // Read reads the next response from the wire. A valid response might be 355 // returned together with an ErrPersistEOF, which means that the remote 356 // requested that this be the last request serviced. Read can be called 357 // concurrently with Write, but not with another Read. 358 func (cc *ClientConn) Read(req *http.Request) (resp *http.Response, err error) { 359 // Retrieve the pipeline ID of this request/response pair 360 cc.mu.Lock() 361 id, ok := cc.pipereq[req] 362 delete(cc.pipereq, req) 363 if !ok { 364 cc.mu.Unlock() 365 return nil, ErrPipeline 366 } 367 cc.mu.Unlock() 368 369 // Ensure pipeline order 370 cc.pipe.StartResponse(id) 371 defer cc.pipe.EndResponse(id) 372 373 cc.mu.Lock() 374 if cc.re != nil { 375 defer cc.mu.Unlock() 376 return nil, cc.re 377 } 378 if cc.r == nil { // connection closed by user in the meantime 379 defer cc.mu.Unlock() 380 return nil, errClosed 381 } 382 r := cc.r 383 lastbody := cc.lastbody 384 cc.lastbody = nil 385 cc.mu.Unlock() 386 387 // Make sure body is fully consumed, even if user does not call body.Close 388 if lastbody != nil { 389 // body.Close is assumed to be idempotent and multiple calls to 390 // it should return the error that its first invocation 391 // returned. 392 err = lastbody.Close() 393 if err != nil { 394 cc.mu.Lock() 395 defer cc.mu.Unlock() 396 cc.re = err 397 return nil, err 398 } 399 } 400 401 resp, err = http.ReadResponse(r, req) 402 cc.mu.Lock() 403 defer cc.mu.Unlock() 404 if err != nil { 405 cc.re = err 406 return resp, err 407 } 408 cc.lastbody = resp.Body 409 410 cc.nread++ 411 412 if resp.Close { 413 cc.re = ErrPersistEOF // don't send any more requests 414 return resp, cc.re 415 } 416 return resp, err 417 } 418 419 // Do is convenience method that writes a request and reads a response. 420 func (cc *ClientConn) Do(req *http.Request) (*http.Response, error) { 421 err := cc.Write(req) 422 if err != nil { 423 return nil, err 424 } 425 return cc.Read(req) 426 }