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