github.com/gocuntian/go@v0.0.0-20160610041250-fee02d270bf8/src/net/http/transport.go (about) 1 // Copyright 2011 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 // HTTP client implementation. See RFC 2616. 6 // 7 // This is the low-level Transport implementation of RoundTripper. 8 // The high-level interface is in client.go. 9 10 package http 11 12 import ( 13 "bufio" 14 "compress/gzip" 15 "container/list" 16 "context" 17 "crypto/tls" 18 "errors" 19 "fmt" 20 "io" 21 "log" 22 "net" 23 "net/http/httptrace" 24 "net/url" 25 "os" 26 "strings" 27 "sync" 28 "time" 29 30 "golang.org/x/net/lex/httplex" 31 ) 32 33 // DefaultTransport is the default implementation of Transport and is 34 // used by DefaultClient. It establishes network connections as needed 35 // and caches them for reuse by subsequent calls. It uses HTTP proxies 36 // as directed by the $HTTP_PROXY and $NO_PROXY (or $http_proxy and 37 // $no_proxy) environment variables. 38 var DefaultTransport RoundTripper = &Transport{ 39 Proxy: ProxyFromEnvironment, 40 DialContext: (&net.Dialer{ 41 Timeout: 30 * time.Second, 42 KeepAlive: 30 * time.Second, 43 }).DialContext, 44 MaxIdleConns: 100, 45 IdleConnTimeout: 90 * time.Second, 46 TLSHandshakeTimeout: 10 * time.Second, 47 ExpectContinueTimeout: 1 * time.Second, 48 } 49 50 // DefaultMaxIdleConnsPerHost is the default value of Transport's 51 // MaxIdleConnsPerHost. 52 const DefaultMaxIdleConnsPerHost = 2 53 54 // Transport is an implementation of RoundTripper that supports HTTP, 55 // HTTPS, and HTTP proxies (for either HTTP or HTTPS with CONNECT). 56 // 57 // By default, Transport caches connections for future re-use. 58 // This may leave many open connections when accessing many hosts. 59 // This behavior can be managed using Transport's CloseIdleConnections method 60 // and the MaxIdleConnsPerHost and DisableKeepAlives fields. 61 // 62 // Transports should be reused instead of created as needed. 63 // Transports are safe for concurrent use by multiple goroutines. 64 // 65 // A Transport is a low-level primitive for making HTTP and HTTPS requests. 66 // For high-level functionality, such as cookies and redirects, see Client. 67 // 68 // Transport uses HTTP/1.1 for HTTP URLs and either HTTP/1.1 or HTTP/2 69 // for HTTPS URLs, depending on whether the server supports HTTP/2. 70 // See the package docs for more about HTTP/2. 71 type Transport struct { 72 idleMu sync.Mutex 73 wantIdle bool // user has requested to close all idle conns 74 idleConn map[connectMethodKey][]*persistConn // most recently used at end 75 idleConnCh map[connectMethodKey]chan *persistConn 76 idleLRU connLRU 77 78 reqMu sync.Mutex 79 reqCanceler map[*Request]func() 80 81 altMu sync.RWMutex 82 altProto map[string]RoundTripper // nil or map of URI scheme => RoundTripper 83 84 // Proxy specifies a function to return a proxy for a given 85 // Request. If the function returns a non-nil error, the 86 // request is aborted with the provided error. 87 // If Proxy is nil or returns a nil *URL, no proxy is used. 88 Proxy func(*Request) (*url.URL, error) 89 90 // DialContext specifies the dial function for creating unencrypted TCP connections. 91 // If DialContext is nil (and the deprecated Dial below is also nil), 92 // then the transport dials using package net. 93 DialContext func(ctx context.Context, network, addr string) (net.Conn, error) 94 95 // Dial specifies the dial function for creating unencrypted TCP connections. 96 // 97 // Deprecated: Use DialContext instead, which allows the transport 98 // to cancel dials as soon as they are no longer needed. 99 // If both are set, DialContext takes priority. 100 Dial func(network, addr string) (net.Conn, error) 101 102 // DialTLS specifies an optional dial function for creating 103 // TLS connections for non-proxied HTTPS requests. 104 // 105 // If DialTLS is nil, Dial and TLSClientConfig are used. 106 // 107 // If DialTLS is set, the Dial hook is not used for HTTPS 108 // requests and the TLSClientConfig and TLSHandshakeTimeout 109 // are ignored. The returned net.Conn is assumed to already be 110 // past the TLS handshake. 111 DialTLS func(network, addr string) (net.Conn, error) 112 113 // TLSClientConfig specifies the TLS configuration to use with 114 // tls.Client. If nil, the default configuration is used. 115 TLSClientConfig *tls.Config 116 117 // TLSHandshakeTimeout specifies the maximum amount of time waiting to 118 // wait for a TLS handshake. Zero means no timeout. 119 TLSHandshakeTimeout time.Duration 120 121 // DisableKeepAlives, if true, prevents re-use of TCP connections 122 // between different HTTP requests. 123 DisableKeepAlives bool 124 125 // DisableCompression, if true, prevents the Transport from 126 // requesting compression with an "Accept-Encoding: gzip" 127 // request header when the Request contains no existing 128 // Accept-Encoding value. If the Transport requests gzip on 129 // its own and gets a gzipped response, it's transparently 130 // decoded in the Response.Body. However, if the user 131 // explicitly requested gzip it is not automatically 132 // uncompressed. 133 DisableCompression bool 134 135 // MaxIdleConns controls the maximum number of idle (keep-alive) 136 // connections across all hosts. Zero means no limit. 137 MaxIdleConns int 138 139 // MaxIdleConnsPerHost, if non-zero, controls the maximum idle 140 // (keep-alive) connections to keep per-host. If zero, 141 // DefaultMaxIdleConnsPerHost is used. 142 MaxIdleConnsPerHost int 143 144 // IdleConnTimeout is the maximum amount of time an idle 145 // (keep-alive) connection will remain idle before closing 146 // itself. 147 // Zero means no limit. 148 IdleConnTimeout time.Duration 149 150 // ResponseHeaderTimeout, if non-zero, specifies the amount of 151 // time to wait for a server's response headers after fully 152 // writing the request (including its body, if any). This 153 // time does not include the time to read the response body. 154 ResponseHeaderTimeout time.Duration 155 156 // ExpectContinueTimeout, if non-zero, specifies the amount of 157 // time to wait for a server's first response headers after fully 158 // writing the request headers if the request has an 159 // "Expect: 100-continue" header. Zero means no timeout. 160 // This time does not include the time to send the request header. 161 ExpectContinueTimeout time.Duration 162 163 // TLSNextProto specifies how the Transport switches to an 164 // alternate protocol (such as HTTP/2) after a TLS NPN/ALPN 165 // protocol negotiation. If Transport dials an TLS connection 166 // with a non-empty protocol name and TLSNextProto contains a 167 // map entry for that key (such as "h2"), then the func is 168 // called with the request's authority (such as "example.com" 169 // or "example.com:1234") and the TLS connection. The function 170 // must return a RoundTripper that then handles the request. 171 // If TLSNextProto is nil, HTTP/2 support is enabled automatically. 172 TLSNextProto map[string]func(authority string, c *tls.Conn) RoundTripper 173 174 // MaxResponseHeaderBytes specifies a limit on how many 175 // response bytes are allowed in the server's response 176 // header. 177 // 178 // Zero means to use a default limit. 179 MaxResponseHeaderBytes int64 180 181 // nextProtoOnce guards initialization of TLSNextProto and 182 // h2transport (via onceSetNextProtoDefaults) 183 nextProtoOnce sync.Once 184 h2transport *http2Transport // non-nil if http2 wired up 185 186 // TODO: tunable on max per-host TCP dials in flight (Issue 13957) 187 } 188 189 // onceSetNextProtoDefaults initializes TLSNextProto. 190 // It must be called via t.nextProtoOnce.Do. 191 func (t *Transport) onceSetNextProtoDefaults() { 192 if strings.Contains(os.Getenv("GODEBUG"), "http2client=0") { 193 return 194 } 195 if t.TLSNextProto != nil { 196 // This is the documented way to disable http2 on a 197 // Transport. 198 return 199 } 200 if t.TLSClientConfig != nil || t.Dial != nil || t.DialTLS != nil { 201 // Be conservative and don't automatically enable 202 // http2 if they've specified a custom TLS config or 203 // custom dialers. Let them opt-in themselves via 204 // http2.ConfigureTransport so we don't surprise them 205 // by modifying their tls.Config. Issue 14275. 206 return 207 } 208 t2, err := http2configureTransport(t) 209 if err != nil { 210 log.Printf("Error enabling Transport HTTP/2 support: %v", err) 211 return 212 } 213 t.h2transport = t2 214 215 // Auto-configure the http2.Transport's MaxHeaderListSize from 216 // the http.Transport's MaxResponseHeaderBytes. They don't 217 // exactly mean the same thing, but they're close. 218 // 219 // TODO: also add this to x/net/http2.Configure Transport, behind 220 // a +build go1.7 build tag: 221 if limit1 := t.MaxResponseHeaderBytes; limit1 != 0 && t2.MaxHeaderListSize == 0 { 222 const h2max = 1<<32 - 1 223 if limit1 >= h2max { 224 t2.MaxHeaderListSize = h2max 225 } else { 226 t2.MaxHeaderListSize = uint32(limit1) 227 } 228 } 229 } 230 231 // ProxyFromEnvironment returns the URL of the proxy to use for a 232 // given request, as indicated by the environment variables 233 // HTTP_PROXY, HTTPS_PROXY and NO_PROXY (or the lowercase versions 234 // thereof). HTTPS_PROXY takes precedence over HTTP_PROXY for https 235 // requests. 236 // 237 // The environment values may be either a complete URL or a 238 // "host[:port]", in which case the "http" scheme is assumed. 239 // An error is returned if the value is a different form. 240 // 241 // A nil URL and nil error are returned if no proxy is defined in the 242 // environment, or a proxy should not be used for the given request, 243 // as defined by NO_PROXY. 244 // 245 // As a special case, if req.URL.Host is "localhost" (with or without 246 // a port number), then a nil URL and nil error will be returned. 247 func ProxyFromEnvironment(req *Request) (*url.URL, error) { 248 var proxy string 249 if req.URL.Scheme == "https" { 250 proxy = httpsProxyEnv.Get() 251 } 252 if proxy == "" { 253 proxy = httpProxyEnv.Get() 254 } 255 if proxy == "" { 256 return nil, nil 257 } 258 if !useProxy(canonicalAddr(req.URL)) { 259 return nil, nil 260 } 261 proxyURL, err := url.Parse(proxy) 262 if err != nil || !strings.HasPrefix(proxyURL.Scheme, "http") { 263 // proxy was bogus. Try prepending "http://" to it and 264 // see if that parses correctly. If not, we fall 265 // through and complain about the original one. 266 if proxyURL, err := url.Parse("http://" + proxy); err == nil { 267 return proxyURL, nil 268 } 269 } 270 if err != nil { 271 return nil, fmt.Errorf("invalid proxy address %q: %v", proxy, err) 272 } 273 return proxyURL, nil 274 } 275 276 // ProxyURL returns a proxy function (for use in a Transport) 277 // that always returns the same URL. 278 func ProxyURL(fixedURL *url.URL) func(*Request) (*url.URL, error) { 279 return func(*Request) (*url.URL, error) { 280 return fixedURL, nil 281 } 282 } 283 284 // transportRequest is a wrapper around a *Request that adds 285 // optional extra headers to write. 286 type transportRequest struct { 287 *Request // original request, not to be mutated 288 extra Header // extra headers to write, or nil 289 trace *httptrace.ClientTrace // optional 290 } 291 292 func (tr *transportRequest) extraHeaders() Header { 293 if tr.extra == nil { 294 tr.extra = make(Header) 295 } 296 return tr.extra 297 } 298 299 // RoundTrip implements the RoundTripper interface. 300 // 301 // For higher-level HTTP client support (such as handling of cookies 302 // and redirects), see Get, Post, and the Client type. 303 func (t *Transport) RoundTrip(req *Request) (*Response, error) { 304 t.nextProtoOnce.Do(t.onceSetNextProtoDefaults) 305 ctx := req.Context() 306 trace := httptrace.ContextClientTrace(ctx) 307 308 if req.URL == nil { 309 req.closeBody() 310 return nil, errors.New("http: nil Request.URL") 311 } 312 if req.Header == nil { 313 req.closeBody() 314 return nil, errors.New("http: nil Request.Header") 315 } 316 scheme := req.URL.Scheme 317 isHTTP := scheme == "http" || scheme == "https" 318 if isHTTP { 319 for k, vv := range req.Header { 320 if !httplex.ValidHeaderFieldName(k) { 321 return nil, fmt.Errorf("net/http: invalid header field name %q", k) 322 } 323 for _, v := range vv { 324 if !httplex.ValidHeaderFieldValue(v) { 325 return nil, fmt.Errorf("net/http: invalid header field value %q for key %v", v, k) 326 } 327 } 328 } 329 } 330 // TODO(bradfitz): switch to atomic.Value for this map instead of RWMutex 331 t.altMu.RLock() 332 altRT := t.altProto[scheme] 333 t.altMu.RUnlock() 334 if altRT != nil { 335 if resp, err := altRT.RoundTrip(req); err != ErrSkipAltProtocol { 336 return resp, err 337 } 338 } 339 if !isHTTP { 340 req.closeBody() 341 return nil, &badStringError{"unsupported protocol scheme", scheme} 342 } 343 if req.Method != "" && !validMethod(req.Method) { 344 return nil, fmt.Errorf("net/http: invalid method %q", req.Method) 345 } 346 if req.URL.Host == "" { 347 req.closeBody() 348 return nil, errors.New("http: no Host in request URL") 349 } 350 351 for { 352 // treq gets modified by roundTrip, so we need to recreate for each retry. 353 treq := &transportRequest{Request: req, trace: trace} 354 cm, err := t.connectMethodForRequest(treq) 355 if err != nil { 356 req.closeBody() 357 return nil, err 358 } 359 360 // Get the cached or newly-created connection to either the 361 // host (for http or https), the http proxy, or the http proxy 362 // pre-CONNECTed to https server. In any case, we'll be ready 363 // to send it requests. 364 pconn, err := t.getConn(treq, cm) 365 if err != nil { 366 t.setReqCanceler(req, nil) 367 req.closeBody() 368 return nil, err 369 } 370 371 var resp *Response 372 if pconn.alt != nil { 373 // HTTP/2 path. 374 t.setReqCanceler(req, nil) // not cancelable with CancelRequest 375 resp, err = pconn.alt.RoundTrip(req) 376 } else { 377 resp, err = pconn.roundTrip(treq) 378 } 379 if err == nil { 380 return resp, nil 381 } 382 if !pconn.shouldRetryRequest(req, err) { 383 return nil, err 384 } 385 testHookRoundTripRetried() 386 } 387 } 388 389 // shouldRetryRequest reports whether we should retry sending a failed 390 // HTTP request on a new connection. The non-nil input error is the 391 // error from roundTrip. 392 func (pc *persistConn) shouldRetryRequest(req *Request, err error) bool { 393 if err == errMissingHost { 394 // User error. 395 return false 396 } 397 if !pc.isReused() { 398 // This was a fresh connection. There's no reason the server 399 // should've hung up on us. 400 // 401 // Also, if we retried now, we could loop forever 402 // creating new connections and retrying if the server 403 // is just hanging up on us because it doesn't like 404 // our request (as opposed to sending an error). 405 return false 406 } 407 if !req.isReplayable() { 408 // Don't retry non-idempotent requests. 409 410 // TODO: swap the nothingWrittenError and isReplayable checks, 411 // putting the "if nothingWrittenError => return true" case 412 // first, per golang.org/issue/15723 413 return false 414 } 415 if _, ok := err.(nothingWrittenError); ok { 416 // We never wrote anything, so it's safe to retry. 417 return true 418 } 419 if err == errServerClosedIdle || err == errServerClosedConn { 420 return true 421 } 422 return false // conservatively 423 } 424 425 // ErrSkipAltProtocol is a sentinel error value defined by Transport.RegisterProtocol. 426 var ErrSkipAltProtocol = errors.New("net/http: skip alternate protocol") 427 428 // RegisterProtocol registers a new protocol with scheme. 429 // The Transport will pass requests using the given scheme to rt. 430 // It is rt's responsibility to simulate HTTP request semantics. 431 // 432 // RegisterProtocol can be used by other packages to provide 433 // implementations of protocol schemes like "ftp" or "file". 434 // 435 // If rt.RoundTrip returns ErrSkipAltProtocol, the Transport will 436 // handle the RoundTrip itself for that one request, as if the 437 // protocol were not registered. 438 func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper) { 439 t.altMu.Lock() 440 defer t.altMu.Unlock() 441 if t.altProto == nil { 442 t.altProto = make(map[string]RoundTripper) 443 } 444 if _, exists := t.altProto[scheme]; exists { 445 panic("protocol " + scheme + " already registered") 446 } 447 t.altProto[scheme] = rt 448 } 449 450 // CloseIdleConnections closes any connections which were previously 451 // connected from previous requests but are now sitting idle in 452 // a "keep-alive" state. It does not interrupt any connections currently 453 // in use. 454 func (t *Transport) CloseIdleConnections() { 455 t.nextProtoOnce.Do(t.onceSetNextProtoDefaults) 456 t.idleMu.Lock() 457 m := t.idleConn 458 t.idleConn = nil 459 t.idleConnCh = nil 460 t.wantIdle = true 461 t.idleLRU = connLRU{} 462 t.idleMu.Unlock() 463 for _, conns := range m { 464 for _, pconn := range conns { 465 pconn.close(errCloseIdleConns) 466 } 467 } 468 if t2 := t.h2transport; t2 != nil { 469 t2.CloseIdleConnections() 470 } 471 } 472 473 // CancelRequest cancels an in-flight request by closing its connection. 474 // CancelRequest should only be called after RoundTrip has returned. 475 // 476 // Deprecated: Use Request.Cancel instead. CancelRequest cannot cancel 477 // HTTP/2 requests. 478 func (t *Transport) CancelRequest(req *Request) { 479 t.reqMu.Lock() 480 cancel := t.reqCanceler[req] 481 delete(t.reqCanceler, req) 482 t.reqMu.Unlock() 483 if cancel != nil { 484 cancel() 485 } 486 } 487 488 // 489 // Private implementation past this point. 490 // 491 492 var ( 493 httpProxyEnv = &envOnce{ 494 names: []string{"HTTP_PROXY", "http_proxy"}, 495 } 496 httpsProxyEnv = &envOnce{ 497 names: []string{"HTTPS_PROXY", "https_proxy"}, 498 } 499 noProxyEnv = &envOnce{ 500 names: []string{"NO_PROXY", "no_proxy"}, 501 } 502 ) 503 504 // envOnce looks up an environment variable (optionally by multiple 505 // names) once. It mitigates expensive lookups on some platforms 506 // (e.g. Windows). 507 type envOnce struct { 508 names []string 509 once sync.Once 510 val string 511 } 512 513 func (e *envOnce) Get() string { 514 e.once.Do(e.init) 515 return e.val 516 } 517 518 func (e *envOnce) init() { 519 for _, n := range e.names { 520 e.val = os.Getenv(n) 521 if e.val != "" { 522 return 523 } 524 } 525 } 526 527 // reset is used by tests 528 func (e *envOnce) reset() { 529 e.once = sync.Once{} 530 e.val = "" 531 } 532 533 func (t *Transport) connectMethodForRequest(treq *transportRequest) (cm connectMethod, err error) { 534 cm.targetScheme = treq.URL.Scheme 535 cm.targetAddr = canonicalAddr(treq.URL) 536 if t.Proxy != nil { 537 cm.proxyURL, err = t.Proxy(treq.Request) 538 } 539 return cm, err 540 } 541 542 // proxyAuth returns the Proxy-Authorization header to set 543 // on requests, if applicable. 544 func (cm *connectMethod) proxyAuth() string { 545 if cm.proxyURL == nil { 546 return "" 547 } 548 if u := cm.proxyURL.User; u != nil { 549 username := u.Username() 550 password, _ := u.Password() 551 return "Basic " + basicAuth(username, password) 552 } 553 return "" 554 } 555 556 // error values for debugging and testing, not seen by users. 557 var ( 558 errKeepAlivesDisabled = errors.New("http: putIdleConn: keep alives disabled") 559 errConnBroken = errors.New("http: putIdleConn: connection is in bad state") 560 errWantIdle = errors.New("http: putIdleConn: CloseIdleConnections was called") 561 errTooManyIdle = errors.New("http: putIdleConn: too many idle connections") 562 errTooManyIdleHost = errors.New("http: putIdleConn: too many idle connections for host") 563 errCloseIdleConns = errors.New("http: CloseIdleConnections called") 564 errReadLoopExiting = errors.New("http: persistConn.readLoop exiting") 565 errServerClosedIdle = errors.New("http: server closed idle connection") 566 errServerClosedConn = errors.New("http: server closed connection") 567 errIdleConnTimeout = errors.New("http: idle connection timeout") 568 ) 569 570 func (t *Transport) putOrCloseIdleConn(pconn *persistConn) { 571 if err := t.tryPutIdleConn(pconn); err != nil { 572 pconn.close(err) 573 } 574 } 575 576 func (t *Transport) maxIdleConnsPerHost() int { 577 if v := t.MaxIdleConnsPerHost; v != 0 { 578 return v 579 } 580 return DefaultMaxIdleConnsPerHost 581 } 582 583 // tryPutIdleConn adds pconn to the list of idle persistent connections awaiting 584 // a new request. 585 // If pconn is no longer needed or not in a good state, tryPutIdleConn returns 586 // an error explaining why it wasn't registered. 587 // tryPutIdleConn does not close pconn. Use putOrCloseIdleConn instead for that. 588 func (t *Transport) tryPutIdleConn(pconn *persistConn) error { 589 if t.DisableKeepAlives || t.MaxIdleConnsPerHost < 0 { 590 return errKeepAlivesDisabled 591 } 592 if pconn.isBroken() { 593 return errConnBroken 594 } 595 pconn.markReused() 596 key := pconn.cacheKey 597 598 t.idleMu.Lock() 599 defer t.idleMu.Unlock() 600 601 waitingDialer := t.idleConnCh[key] 602 select { 603 case waitingDialer <- pconn: 604 // We're done with this pconn and somebody else is 605 // currently waiting for a conn of this type (they're 606 // actively dialing, but this conn is ready 607 // first). Chrome calls this socket late binding. See 608 // https://insouciant.org/tech/connection-management-in-chromium/ 609 return nil 610 default: 611 if waitingDialer != nil { 612 // They had populated this, but their dial won 613 // first, so we can clean up this map entry. 614 delete(t.idleConnCh, key) 615 } 616 } 617 if t.wantIdle { 618 return errWantIdle 619 } 620 if t.idleConn == nil { 621 t.idleConn = make(map[connectMethodKey][]*persistConn) 622 } 623 idles := t.idleConn[key] 624 if len(idles) >= t.maxIdleConnsPerHost() { 625 return errTooManyIdleHost 626 } 627 for _, exist := range idles { 628 if exist == pconn { 629 log.Fatalf("dup idle pconn %p in freelist", pconn) 630 } 631 } 632 t.idleConn[key] = append(idles, pconn) 633 t.idleLRU.add(pconn) 634 if t.MaxIdleConns != 0 && t.idleLRU.len() > t.MaxIdleConns { 635 oldest := t.idleLRU.removeOldest() 636 oldest.close(errTooManyIdle) 637 t.removeIdleConnLocked(oldest) 638 } 639 if t.IdleConnTimeout > 0 { 640 if pconn.idleTimer != nil { 641 pconn.idleTimer.Reset(t.IdleConnTimeout) 642 } else { 643 pconn.idleTimer = time.AfterFunc(t.IdleConnTimeout, pconn.closeConnIfStillIdle) 644 } 645 } 646 pconn.idleAt = time.Now() 647 return nil 648 } 649 650 // getIdleConnCh returns a channel to receive and return idle 651 // persistent connection for the given connectMethod. 652 // It may return nil, if persistent connections are not being used. 653 func (t *Transport) getIdleConnCh(cm connectMethod) chan *persistConn { 654 if t.DisableKeepAlives { 655 return nil 656 } 657 key := cm.key() 658 t.idleMu.Lock() 659 defer t.idleMu.Unlock() 660 t.wantIdle = false 661 if t.idleConnCh == nil { 662 t.idleConnCh = make(map[connectMethodKey]chan *persistConn) 663 } 664 ch, ok := t.idleConnCh[key] 665 if !ok { 666 ch = make(chan *persistConn) 667 t.idleConnCh[key] = ch 668 } 669 return ch 670 } 671 672 func (t *Transport) getIdleConn(cm connectMethod) (pconn *persistConn, idleSince time.Time) { 673 key := cm.key() 674 t.idleMu.Lock() 675 defer t.idleMu.Unlock() 676 for { 677 pconns, ok := t.idleConn[key] 678 if !ok { 679 return nil, time.Time{} 680 } 681 if len(pconns) == 1 { 682 pconn = pconns[0] 683 delete(t.idleConn, key) 684 } else { 685 // 2 or more cached connections; use the most 686 // recently used one at the end. 687 pconn = pconns[len(pconns)-1] 688 t.idleConn[key] = pconns[:len(pconns)-1] 689 } 690 t.idleLRU.remove(pconn) 691 if pconn.isBroken() { 692 // There is a tiny window where this is 693 // possible, between the connecting dying and 694 // the persistConn readLoop calling 695 // Transport.removeIdleConn. Just skip it and 696 // carry on. 697 continue 698 } 699 if pconn.idleTimer != nil && !pconn.idleTimer.Stop() { 700 // We picked this conn at the ~same time it 701 // was expiring and it's trying to close 702 // itself in another goroutine. Don't use it. 703 continue 704 } 705 return pconn, pconn.idleAt 706 } 707 } 708 709 // removeIdleConn marks pconn as dead. 710 func (t *Transport) removeIdleConn(pconn *persistConn) { 711 t.idleMu.Lock() 712 defer t.idleMu.Unlock() 713 t.removeIdleConnLocked(pconn) 714 } 715 716 // t.idleMu must be held. 717 func (t *Transport) removeIdleConnLocked(pconn *persistConn) { 718 if pconn.idleTimer != nil { 719 pconn.idleTimer.Stop() 720 } 721 t.idleLRU.remove(pconn) 722 key := pconn.cacheKey 723 pconns, _ := t.idleConn[key] 724 switch len(pconns) { 725 case 0: 726 // Nothing 727 case 1: 728 if pconns[0] == pconn { 729 delete(t.idleConn, key) 730 } 731 default: 732 for i, v := range pconns { 733 if v != pconn { 734 continue 735 } 736 // Slide down, keeping most recently-used 737 // conns at the end. 738 copy(pconns[i:], pconns[i+1:]) 739 t.idleConn[key] = pconns[:len(pconns)-1] 740 break 741 } 742 } 743 } 744 745 func (t *Transport) setReqCanceler(r *Request, fn func()) { 746 t.reqMu.Lock() 747 defer t.reqMu.Unlock() 748 if t.reqCanceler == nil { 749 t.reqCanceler = make(map[*Request]func()) 750 } 751 if fn != nil { 752 t.reqCanceler[r] = fn 753 } else { 754 delete(t.reqCanceler, r) 755 } 756 } 757 758 // replaceReqCanceler replaces an existing cancel function. If there is no cancel function 759 // for the request, we don't set the function and return false. 760 // Since CancelRequest will clear the canceler, we can use the return value to detect if 761 // the request was canceled since the last setReqCancel call. 762 func (t *Transport) replaceReqCanceler(r *Request, fn func()) bool { 763 t.reqMu.Lock() 764 defer t.reqMu.Unlock() 765 _, ok := t.reqCanceler[r] 766 if !ok { 767 return false 768 } 769 if fn != nil { 770 t.reqCanceler[r] = fn 771 } else { 772 delete(t.reqCanceler, r) 773 } 774 return true 775 } 776 777 var zeroDialer net.Dialer 778 779 func (t *Transport) dial(ctx context.Context, network, addr string) (net.Conn, error) { 780 if t.DialContext != nil { 781 return t.DialContext(ctx, network, addr) 782 } 783 if t.Dial != nil { 784 c, err := t.Dial(network, addr) 785 if c == nil && err == nil { 786 err = errors.New("net/http: Transport.Dial hook returned (nil, nil)") 787 } 788 return c, err 789 } 790 return zeroDialer.DialContext(ctx, network, addr) 791 } 792 793 // getConn dials and creates a new persistConn to the target as 794 // specified in the connectMethod. This includes doing a proxy CONNECT 795 // and/or setting up TLS. If this doesn't return an error, the persistConn 796 // is ready to write requests to. 797 func (t *Transport) getConn(treq *transportRequest, cm connectMethod) (*persistConn, error) { 798 req := treq.Request 799 trace := treq.trace 800 ctx := req.Context() 801 if trace != nil && trace.GetConn != nil { 802 trace.GetConn(cm.addr()) 803 } 804 if pc, idleSince := t.getIdleConn(cm); pc != nil { 805 if trace != nil && trace.GotConn != nil { 806 trace.GotConn(pc.gotIdleConnTrace(idleSince)) 807 } 808 // set request canceler to some non-nil function so we 809 // can detect whether it was cleared between now and when 810 // we enter roundTrip 811 t.setReqCanceler(req, func() {}) 812 return pc, nil 813 } 814 815 type dialRes struct { 816 pc *persistConn 817 err error 818 } 819 dialc := make(chan dialRes) 820 821 // Copy these hooks so we don't race on the postPendingDial in 822 // the goroutine we launch. Issue 11136. 823 testHookPrePendingDial := testHookPrePendingDial 824 testHookPostPendingDial := testHookPostPendingDial 825 826 handlePendingDial := func() { 827 testHookPrePendingDial() 828 go func() { 829 if v := <-dialc; v.err == nil { 830 t.putOrCloseIdleConn(v.pc) 831 } 832 testHookPostPendingDial() 833 }() 834 } 835 836 cancelc := make(chan struct{}) 837 t.setReqCanceler(req, func() { close(cancelc) }) 838 839 go func() { 840 pc, err := t.dialConn(ctx, cm) 841 dialc <- dialRes{pc, err} 842 }() 843 844 idleConnCh := t.getIdleConnCh(cm) 845 select { 846 case v := <-dialc: 847 // Our dial finished. 848 if trace != nil && trace.GotConn != nil && v.pc != nil && v.pc.alt == nil { 849 trace.GotConn(httptrace.GotConnInfo{Conn: v.pc.conn}) 850 } 851 return v.pc, v.err 852 case pc := <-idleConnCh: 853 // Another request finished first and its net.Conn 854 // became available before our dial. Or somebody 855 // else's dial that they didn't use. 856 // But our dial is still going, so give it away 857 // when it finishes: 858 handlePendingDial() 859 if trace != nil && trace.GotConn != nil { 860 trace.GotConn(httptrace.GotConnInfo{Conn: pc.conn, Reused: pc.isReused()}) 861 } 862 return pc, nil 863 case <-req.Cancel: 864 handlePendingDial() 865 return nil, errRequestCanceledConn 866 case <-req.Context().Done(): 867 handlePendingDial() 868 return nil, errRequestCanceledConn 869 case <-cancelc: 870 handlePendingDial() 871 return nil, errRequestCanceledConn 872 } 873 } 874 875 func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (*persistConn, error) { 876 pconn := &persistConn{ 877 t: t, 878 cacheKey: cm.key(), 879 reqch: make(chan requestAndChan, 1), 880 writech: make(chan writeRequest, 1), 881 closech: make(chan struct{}), 882 writeErrCh: make(chan error, 1), 883 writeLoopDone: make(chan struct{}), 884 } 885 tlsDial := t.DialTLS != nil && cm.targetScheme == "https" && cm.proxyURL == nil 886 if tlsDial { 887 var err error 888 pconn.conn, err = t.DialTLS("tcp", cm.addr()) 889 if err != nil { 890 return nil, err 891 } 892 if pconn.conn == nil { 893 return nil, errors.New("net/http: Transport.DialTLS returned (nil, nil)") 894 } 895 if tc, ok := pconn.conn.(*tls.Conn); ok { 896 // Handshake here, in case DialTLS didn't. TLSNextProto below 897 // depends on it for knowing the connection state. 898 if err := tc.Handshake(); err != nil { 899 go pconn.conn.Close() 900 return nil, err 901 } 902 cs := tc.ConnectionState() 903 pconn.tlsState = &cs 904 } 905 } else { 906 conn, err := t.dial(ctx, "tcp", cm.addr()) 907 if err != nil { 908 if cm.proxyURL != nil { 909 err = fmt.Errorf("http: error connecting to proxy %s: %v", cm.proxyURL, err) 910 } 911 return nil, err 912 } 913 pconn.conn = conn 914 } 915 916 // Proxy setup. 917 switch { 918 case cm.proxyURL == nil: 919 // Do nothing. Not using a proxy. 920 case cm.targetScheme == "http": 921 pconn.isProxy = true 922 if pa := cm.proxyAuth(); pa != "" { 923 pconn.mutateHeaderFunc = func(h Header) { 924 h.Set("Proxy-Authorization", pa) 925 } 926 } 927 case cm.targetScheme == "https": 928 conn := pconn.conn 929 connectReq := &Request{ 930 Method: "CONNECT", 931 URL: &url.URL{Opaque: cm.targetAddr}, 932 Host: cm.targetAddr, 933 Header: make(Header), 934 } 935 if pa := cm.proxyAuth(); pa != "" { 936 connectReq.Header.Set("Proxy-Authorization", pa) 937 } 938 connectReq.Write(conn) 939 940 // Read response. 941 // Okay to use and discard buffered reader here, because 942 // TLS server will not speak until spoken to. 943 br := bufio.NewReader(conn) 944 resp, err := ReadResponse(br, connectReq) 945 if err != nil { 946 conn.Close() 947 return nil, err 948 } 949 if resp.StatusCode != 200 { 950 f := strings.SplitN(resp.Status, " ", 2) 951 conn.Close() 952 return nil, errors.New(f[1]) 953 } 954 } 955 956 if cm.targetScheme == "https" && !tlsDial { 957 // Initiate TLS and check remote host name against certificate. 958 cfg := cloneTLSClientConfig(t.TLSClientConfig) 959 if cfg.ServerName == "" { 960 cfg.ServerName = cm.tlsHost() 961 } 962 plainConn := pconn.conn 963 tlsConn := tls.Client(plainConn, cfg) 964 errc := make(chan error, 2) 965 var timer *time.Timer // for canceling TLS handshake 966 if d := t.TLSHandshakeTimeout; d != 0 { 967 timer = time.AfterFunc(d, func() { 968 errc <- tlsHandshakeTimeoutError{} 969 }) 970 } 971 go func() { 972 err := tlsConn.Handshake() 973 if timer != nil { 974 timer.Stop() 975 } 976 errc <- err 977 }() 978 if err := <-errc; err != nil { 979 plainConn.Close() 980 return nil, err 981 } 982 if !cfg.InsecureSkipVerify { 983 if err := tlsConn.VerifyHostname(cfg.ServerName); err != nil { 984 plainConn.Close() 985 return nil, err 986 } 987 } 988 cs := tlsConn.ConnectionState() 989 pconn.tlsState = &cs 990 pconn.conn = tlsConn 991 } 992 993 if s := pconn.tlsState; s != nil && s.NegotiatedProtocolIsMutual && s.NegotiatedProtocol != "" { 994 if next, ok := t.TLSNextProto[s.NegotiatedProtocol]; ok { 995 return &persistConn{alt: next(cm.targetAddr, pconn.conn.(*tls.Conn))}, nil 996 } 997 } 998 999 pconn.br = bufio.NewReader(pconn) 1000 pconn.bw = bufio.NewWriter(persistConnWriter{pconn}) 1001 go pconn.readLoop() 1002 go pconn.writeLoop() 1003 return pconn, nil 1004 } 1005 1006 // persistConnWriter is the io.Writer written to by pc.bw. 1007 // It accumulates the number of bytes written to the underlying conn, 1008 // so the retry logic can determine whether any bytes made it across 1009 // the wire. 1010 // This is exactly 1 pointer field wide so it can go into an interface 1011 // without allocation. 1012 type persistConnWriter struct { 1013 pc *persistConn 1014 } 1015 1016 func (w persistConnWriter) Write(p []byte) (n int, err error) { 1017 n, err = w.pc.conn.Write(p) 1018 w.pc.nwrite += int64(n) 1019 return 1020 } 1021 1022 // useProxy reports whether requests to addr should use a proxy, 1023 // according to the NO_PROXY or no_proxy environment variable. 1024 // addr is always a canonicalAddr with a host and port. 1025 func useProxy(addr string) bool { 1026 if len(addr) == 0 { 1027 return true 1028 } 1029 host, _, err := net.SplitHostPort(addr) 1030 if err != nil { 1031 return false 1032 } 1033 if host == "localhost" { 1034 return false 1035 } 1036 if ip := net.ParseIP(host); ip != nil { 1037 if ip.IsLoopback() { 1038 return false 1039 } 1040 } 1041 1042 no_proxy := noProxyEnv.Get() 1043 if no_proxy == "*" { 1044 return false 1045 } 1046 1047 addr = strings.ToLower(strings.TrimSpace(addr)) 1048 if hasPort(addr) { 1049 addr = addr[:strings.LastIndex(addr, ":")] 1050 } 1051 1052 for _, p := range strings.Split(no_proxy, ",") { 1053 p = strings.ToLower(strings.TrimSpace(p)) 1054 if len(p) == 0 { 1055 continue 1056 } 1057 if hasPort(p) { 1058 p = p[:strings.LastIndex(p, ":")] 1059 } 1060 if addr == p { 1061 return false 1062 } 1063 if p[0] == '.' && (strings.HasSuffix(addr, p) || addr == p[1:]) { 1064 // no_proxy ".foo.com" matches "bar.foo.com" or "foo.com" 1065 return false 1066 } 1067 if p[0] != '.' && strings.HasSuffix(addr, p) && addr[len(addr)-len(p)-1] == '.' { 1068 // no_proxy "foo.com" matches "bar.foo.com" 1069 return false 1070 } 1071 } 1072 return true 1073 } 1074 1075 // connectMethod is the map key (in its String form) for keeping persistent 1076 // TCP connections alive for subsequent HTTP requests. 1077 // 1078 // A connect method may be of the following types: 1079 // 1080 // Cache key form Description 1081 // ----------------- ------------------------- 1082 // |http|foo.com http directly to server, no proxy 1083 // |https|foo.com https directly to server, no proxy 1084 // http://proxy.com|https|foo.com http to proxy, then CONNECT to foo.com 1085 // http://proxy.com|http http to proxy, http to anywhere after that 1086 // 1087 // Note: no support to https to the proxy yet. 1088 // 1089 type connectMethod struct { 1090 proxyURL *url.URL // nil for no proxy, else full proxy URL 1091 targetScheme string // "http" or "https" 1092 targetAddr string // Not used if proxy + http targetScheme (4th example in table) 1093 } 1094 1095 func (cm *connectMethod) key() connectMethodKey { 1096 proxyStr := "" 1097 targetAddr := cm.targetAddr 1098 if cm.proxyURL != nil { 1099 proxyStr = cm.proxyURL.String() 1100 if cm.targetScheme == "http" { 1101 targetAddr = "" 1102 } 1103 } 1104 return connectMethodKey{ 1105 proxy: proxyStr, 1106 scheme: cm.targetScheme, 1107 addr: targetAddr, 1108 } 1109 } 1110 1111 // addr returns the first hop "host:port" to which we need to TCP connect. 1112 func (cm *connectMethod) addr() string { 1113 if cm.proxyURL != nil { 1114 return canonicalAddr(cm.proxyURL) 1115 } 1116 return cm.targetAddr 1117 } 1118 1119 // tlsHost returns the host name to match against the peer's 1120 // TLS certificate. 1121 func (cm *connectMethod) tlsHost() string { 1122 h := cm.targetAddr 1123 if hasPort(h) { 1124 h = h[:strings.LastIndex(h, ":")] 1125 } 1126 return h 1127 } 1128 1129 // connectMethodKey is the map key version of connectMethod, with a 1130 // stringified proxy URL (or the empty string) instead of a pointer to 1131 // a URL. 1132 type connectMethodKey struct { 1133 proxy, scheme, addr string 1134 } 1135 1136 func (k connectMethodKey) String() string { 1137 // Only used by tests. 1138 return fmt.Sprintf("%s|%s|%s", k.proxy, k.scheme, k.addr) 1139 } 1140 1141 // persistConn wraps a connection, usually a persistent one 1142 // (but may be used for non-keep-alive requests as well) 1143 type persistConn struct { 1144 // alt optionally specifies the TLS NextProto RoundTripper. 1145 // This is used for HTTP/2 today and future protocols later. 1146 // If it's non-nil, the rest of the fields are unused. 1147 alt RoundTripper 1148 1149 t *Transport 1150 cacheKey connectMethodKey 1151 conn net.Conn 1152 tlsState *tls.ConnectionState 1153 br *bufio.Reader // from conn 1154 bw *bufio.Writer // to conn 1155 nwrite int64 // bytes written 1156 reqch chan requestAndChan // written by roundTrip; read by readLoop 1157 writech chan writeRequest // written by roundTrip; read by writeLoop 1158 closech chan struct{} // closed when conn closed 1159 isProxy bool 1160 sawEOF bool // whether we've seen EOF from conn; owned by readLoop 1161 readLimit int64 // bytes allowed to be read; owned by readLoop 1162 // writeErrCh passes the request write error (usually nil) 1163 // from the writeLoop goroutine to the readLoop which passes 1164 // it off to the res.Body reader, which then uses it to decide 1165 // whether or not a connection can be reused. Issue 7569. 1166 writeErrCh chan error 1167 1168 writeLoopDone chan struct{} // closed when write loop ends 1169 1170 // Both guarded by Transport.idleMu: 1171 idleAt time.Time // time it last become idle 1172 idleTimer *time.Timer // holding an AfterFunc to close it 1173 1174 mu sync.Mutex // guards following fields 1175 numExpectedResponses int 1176 closed error // set non-nil when conn is closed, before closech is closed 1177 broken bool // an error has happened on this connection; marked broken so it's not reused. 1178 canceled bool // whether this conn was broken due a CancelRequest 1179 reused bool // whether conn has had successful request/response and is being reused. 1180 // mutateHeaderFunc is an optional func to modify extra 1181 // headers on each outbound request before it's written. (the 1182 // original Request given to RoundTrip is not modified) 1183 mutateHeaderFunc func(Header) 1184 } 1185 1186 func (pc *persistConn) maxHeaderResponseSize() int64 { 1187 if v := pc.t.MaxResponseHeaderBytes; v != 0 { 1188 return v 1189 } 1190 return 10 << 20 // conservative default; same as http2 1191 } 1192 1193 func (pc *persistConn) Read(p []byte) (n int, err error) { 1194 if pc.readLimit <= 0 { 1195 return 0, fmt.Errorf("read limit of %d bytes exhausted", pc.maxHeaderResponseSize()) 1196 } 1197 if int64(len(p)) > pc.readLimit { 1198 p = p[:pc.readLimit] 1199 } 1200 n, err = pc.conn.Read(p) 1201 if err == io.EOF { 1202 pc.sawEOF = true 1203 } 1204 pc.readLimit -= int64(n) 1205 return 1206 } 1207 1208 // isBroken reports whether this connection is in a known broken state. 1209 func (pc *persistConn) isBroken() bool { 1210 pc.mu.Lock() 1211 b := pc.closed != nil 1212 pc.mu.Unlock() 1213 return b 1214 } 1215 1216 // isCanceled reports whether this connection was closed due to CancelRequest. 1217 func (pc *persistConn) isCanceled() bool { 1218 pc.mu.Lock() 1219 defer pc.mu.Unlock() 1220 return pc.canceled 1221 } 1222 1223 // isReused reports whether this connection is in a known broken state. 1224 func (pc *persistConn) isReused() bool { 1225 pc.mu.Lock() 1226 r := pc.reused 1227 pc.mu.Unlock() 1228 return r 1229 } 1230 1231 func (pc *persistConn) gotIdleConnTrace(idleAt time.Time) (t httptrace.GotConnInfo) { 1232 pc.mu.Lock() 1233 defer pc.mu.Unlock() 1234 t.Reused = pc.reused 1235 t.Conn = pc.conn 1236 t.WasIdle = true 1237 if !idleAt.IsZero() { 1238 t.IdleTime = time.Since(idleAt) 1239 } 1240 return 1241 } 1242 1243 func (pc *persistConn) cancelRequest() { 1244 pc.mu.Lock() 1245 defer pc.mu.Unlock() 1246 pc.canceled = true 1247 pc.closeLocked(errRequestCanceled) 1248 } 1249 1250 // closeConnIfStillIdle closes the connection if it's still sitting idle. 1251 // This is what's called by the persistConn's idleTimer, and is run in its 1252 // own goroutine. 1253 func (pc *persistConn) closeConnIfStillIdle() { 1254 t := pc.t 1255 t.idleMu.Lock() 1256 defer t.idleMu.Unlock() 1257 if _, ok := t.idleLRU.m[pc]; !ok { 1258 // Not idle. 1259 return 1260 } 1261 t.removeIdleConnLocked(pc) 1262 pc.close(errIdleConnTimeout) 1263 } 1264 1265 // mapRoundTripErrorFromReadLoop maps the provided readLoop error into 1266 // the error value that should be returned from persistConn.roundTrip. 1267 // 1268 // The startBytesWritten value should be the value of pc.nwrite before the roundTrip 1269 // started writing the request. 1270 func (pc *persistConn) mapRoundTripErrorFromReadLoop(startBytesWritten int64, err error) (out error) { 1271 if err == nil { 1272 return nil 1273 } 1274 if pc.isCanceled() { 1275 return errRequestCanceled 1276 } 1277 if err == errServerClosedIdle || err == errServerClosedConn { 1278 return err 1279 } 1280 if pc.isBroken() { 1281 <-pc.writeLoopDone 1282 if pc.nwrite == startBytesWritten { 1283 return nothingWrittenError{err} 1284 } 1285 } 1286 return err 1287 } 1288 1289 // mapRoundTripErrorAfterClosed returns the error value to be propagated 1290 // up to Transport.RoundTrip method when persistConn.roundTrip sees 1291 // its pc.closech channel close, indicating the persistConn is dead. 1292 // (after closech is closed, pc.closed is valid). 1293 func (pc *persistConn) mapRoundTripErrorAfterClosed(startBytesWritten int64) error { 1294 if pc.isCanceled() { 1295 return errRequestCanceled 1296 } 1297 err := pc.closed 1298 if err == errServerClosedIdle || err == errServerClosedConn { 1299 // Don't decorate 1300 return err 1301 } 1302 1303 // Wait for the writeLoop goroutine to terminated, and then 1304 // see if we actually managed to write anything. If not, we 1305 // can retry the request. 1306 <-pc.writeLoopDone 1307 if pc.nwrite == startBytesWritten { 1308 return nothingWrittenError{err} 1309 } 1310 1311 return fmt.Errorf("net/http: HTTP/1.x transport connection broken: %v", err) 1312 1313 } 1314 1315 func (pc *persistConn) readLoop() { 1316 closeErr := errReadLoopExiting // default value, if not changed below 1317 defer func() { 1318 pc.close(closeErr) 1319 pc.t.removeIdleConn(pc) 1320 }() 1321 1322 tryPutIdleConn := func(trace *httptrace.ClientTrace) bool { 1323 if err := pc.t.tryPutIdleConn(pc); err != nil { 1324 closeErr = err 1325 if trace != nil && trace.PutIdleConn != nil && err != errKeepAlivesDisabled { 1326 trace.PutIdleConn(err) 1327 } 1328 return false 1329 } 1330 if trace != nil && trace.PutIdleConn != nil { 1331 trace.PutIdleConn(nil) 1332 } 1333 return true 1334 } 1335 1336 // eofc is used to block caller goroutines reading from Response.Body 1337 // at EOF until this goroutines has (potentially) added the connection 1338 // back to the idle pool. 1339 eofc := make(chan struct{}) 1340 defer close(eofc) // unblock reader on errors 1341 1342 // Read this once, before loop starts. (to avoid races in tests) 1343 testHookMu.Lock() 1344 testHookReadLoopBeforeNextRead := testHookReadLoopBeforeNextRead 1345 testHookMu.Unlock() 1346 1347 alive := true 1348 for alive { 1349 pc.readLimit = pc.maxHeaderResponseSize() 1350 _, err := pc.br.Peek(1) 1351 1352 pc.mu.Lock() 1353 if pc.numExpectedResponses == 0 { 1354 pc.readLoopPeekFailLocked(err) 1355 pc.mu.Unlock() 1356 return 1357 } 1358 pc.mu.Unlock() 1359 1360 rc := <-pc.reqch 1361 trace := httptrace.ContextClientTrace(rc.req.Context()) 1362 1363 var resp *Response 1364 if err == nil { 1365 resp, err = pc.readResponse(rc, trace) 1366 } else { 1367 err = errServerClosedConn 1368 closeErr = err 1369 } 1370 1371 if err != nil { 1372 if pc.readLimit <= 0 { 1373 err = fmt.Errorf("net/http: server response headers exceeded %d bytes; aborted", pc.maxHeaderResponseSize()) 1374 } 1375 1376 // If we won't be able to retry this request later (from the 1377 // roundTrip goroutine), mark it as done now. 1378 // BEFORE the send on rc.ch, as the client might re-use the 1379 // same *Request pointer, and we don't want to set call 1380 // t.setReqCanceler from this persistConn while the Transport 1381 // potentially spins up a different persistConn for the 1382 // caller's subsequent request. 1383 if !pc.shouldRetryRequest(rc.req, err) { 1384 pc.t.setReqCanceler(rc.req, nil) 1385 } 1386 select { 1387 case rc.ch <- responseAndError{err: err}: 1388 case <-rc.callerGone: 1389 return 1390 } 1391 return 1392 } 1393 pc.readLimit = maxInt64 // effictively no limit for response bodies 1394 1395 pc.mu.Lock() 1396 pc.numExpectedResponses-- 1397 pc.mu.Unlock() 1398 1399 hasBody := rc.req.Method != "HEAD" && resp.ContentLength != 0 1400 1401 if resp.Close || rc.req.Close || resp.StatusCode <= 199 { 1402 // Don't do keep-alive on error if either party requested a close 1403 // or we get an unexpected informational (1xx) response. 1404 // StatusCode 100 is already handled above. 1405 alive = false 1406 } 1407 1408 if !hasBody { 1409 pc.t.setReqCanceler(rc.req, nil) 1410 1411 // Put the idle conn back into the pool before we send the response 1412 // so if they process it quickly and make another request, they'll 1413 // get this same conn. But we use the unbuffered channel 'rc' 1414 // to guarantee that persistConn.roundTrip got out of its select 1415 // potentially waiting for this persistConn to close. 1416 // but after 1417 alive = alive && 1418 !pc.sawEOF && 1419 pc.wroteRequest() && 1420 tryPutIdleConn(trace) 1421 1422 select { 1423 case rc.ch <- responseAndError{res: resp}: 1424 case <-rc.callerGone: 1425 return 1426 } 1427 1428 // Now that they've read from the unbuffered channel, they're safely 1429 // out of the select that also waits on this goroutine to die, so 1430 // we're allowed to exit now if needed (if alive is false) 1431 testHookReadLoopBeforeNextRead() 1432 continue 1433 } 1434 1435 waitForBodyRead := make(chan bool, 2) 1436 body := &bodyEOFSignal{ 1437 body: resp.Body, 1438 earlyCloseFn: func() error { 1439 waitForBodyRead <- false 1440 return nil 1441 1442 }, 1443 fn: func(err error) error { 1444 isEOF := err == io.EOF 1445 waitForBodyRead <- isEOF 1446 if isEOF { 1447 <-eofc // see comment above eofc declaration 1448 } else if err != nil && pc.isCanceled() { 1449 return errRequestCanceled 1450 } 1451 return err 1452 }, 1453 } 1454 1455 resp.Body = body 1456 if rc.addedGzip && resp.Header.Get("Content-Encoding") == "gzip" { 1457 resp.Body = &gzipReader{body: body} 1458 resp.Header.Del("Content-Encoding") 1459 resp.Header.Del("Content-Length") 1460 resp.ContentLength = -1 1461 resp.Uncompressed = true 1462 } 1463 1464 select { 1465 case rc.ch <- responseAndError{res: resp}: 1466 case <-rc.callerGone: 1467 return 1468 } 1469 1470 // Before looping back to the top of this function and peeking on 1471 // the bufio.Reader, wait for the caller goroutine to finish 1472 // reading the response body. (or for cancelation or death) 1473 select { 1474 case bodyEOF := <-waitForBodyRead: 1475 pc.t.setReqCanceler(rc.req, nil) // before pc might return to idle pool 1476 alive = alive && 1477 bodyEOF && 1478 !pc.sawEOF && 1479 pc.wroteRequest() && 1480 tryPutIdleConn(trace) 1481 if bodyEOF { 1482 eofc <- struct{}{} 1483 } 1484 case <-rc.req.Cancel: 1485 alive = false 1486 pc.t.CancelRequest(rc.req) 1487 case <-rc.req.Context().Done(): 1488 alive = false 1489 pc.t.CancelRequest(rc.req) 1490 case <-pc.closech: 1491 alive = false 1492 } 1493 1494 testHookReadLoopBeforeNextRead() 1495 } 1496 } 1497 1498 func (pc *persistConn) readLoopPeekFailLocked(peekErr error) { 1499 if pc.closed != nil { 1500 return 1501 } 1502 if n := pc.br.Buffered(); n > 0 { 1503 buf, _ := pc.br.Peek(n) 1504 log.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v", buf, peekErr) 1505 } 1506 if peekErr == io.EOF { 1507 // common case. 1508 pc.closeLocked(errServerClosedIdle) 1509 } else { 1510 pc.closeLocked(fmt.Errorf("readLoopPeekFailLocked: %v", peekErr)) 1511 } 1512 } 1513 1514 // readResponse reads an HTTP response (or two, in the case of "Expect: 1515 // 100-continue") from the server. It returns the final non-100 one. 1516 // trace is optional. 1517 func (pc *persistConn) readResponse(rc requestAndChan, trace *httptrace.ClientTrace) (resp *Response, err error) { 1518 if trace != nil && trace.GotFirstResponseByte != nil { 1519 if peek, err := pc.br.Peek(1); err == nil && len(peek) == 1 { 1520 trace.GotFirstResponseByte() 1521 } 1522 } 1523 resp, err = ReadResponse(pc.br, rc.req) 1524 if err != nil { 1525 return 1526 } 1527 if rc.continueCh != nil { 1528 if resp.StatusCode == 100 { 1529 if trace != nil && trace.Got100Continue != nil { 1530 trace.Got100Continue() 1531 } 1532 rc.continueCh <- struct{}{} 1533 } else { 1534 close(rc.continueCh) 1535 } 1536 } 1537 if resp.StatusCode == 100 { 1538 pc.readLimit = pc.maxHeaderResponseSize() // reset the limit 1539 resp, err = ReadResponse(pc.br, rc.req) 1540 if err != nil { 1541 return 1542 } 1543 } 1544 resp.TLS = pc.tlsState 1545 return 1546 } 1547 1548 // waitForContinue returns the function to block until 1549 // any response, timeout or connection close. After any of them, 1550 // the function returns a bool which indicates if the body should be sent. 1551 func (pc *persistConn) waitForContinue(continueCh <-chan struct{}) func() bool { 1552 if continueCh == nil { 1553 return nil 1554 } 1555 return func() bool { 1556 timer := time.NewTimer(pc.t.ExpectContinueTimeout) 1557 defer timer.Stop() 1558 1559 select { 1560 case _, ok := <-continueCh: 1561 return ok 1562 case <-timer.C: 1563 return true 1564 case <-pc.closech: 1565 return false 1566 } 1567 } 1568 } 1569 1570 // nothingWrittenError wraps a write errors which ended up writing zero bytes. 1571 type nothingWrittenError struct { 1572 error 1573 } 1574 1575 func (pc *persistConn) writeLoop() { 1576 defer close(pc.writeLoopDone) 1577 for { 1578 select { 1579 case wr := <-pc.writech: 1580 startBytesWritten := pc.nwrite 1581 err := wr.req.Request.write(pc.bw, pc.isProxy, wr.req.extra, pc.waitForContinue(wr.continueCh)) 1582 if err == nil { 1583 err = pc.bw.Flush() 1584 } 1585 if err != nil { 1586 wr.req.Request.closeBody() 1587 if pc.nwrite == startBytesWritten { 1588 err = nothingWrittenError{err} 1589 } 1590 } 1591 pc.writeErrCh <- err // to the body reader, which might recycle us 1592 wr.ch <- err // to the roundTrip function 1593 if err != nil { 1594 pc.close(err) 1595 return 1596 } 1597 case <-pc.closech: 1598 return 1599 } 1600 } 1601 } 1602 1603 // wroteRequest is a check before recycling a connection that the previous write 1604 // (from writeLoop above) happened and was successful. 1605 func (pc *persistConn) wroteRequest() bool { 1606 select { 1607 case err := <-pc.writeErrCh: 1608 // Common case: the write happened well before the response, so 1609 // avoid creating a timer. 1610 return err == nil 1611 default: 1612 // Rare case: the request was written in writeLoop above but 1613 // before it could send to pc.writeErrCh, the reader read it 1614 // all, processed it, and called us here. In this case, give the 1615 // write goroutine a bit of time to finish its send. 1616 // 1617 // Less rare case: We also get here in the legitimate case of 1618 // Issue 7569, where the writer is still writing (or stalled), 1619 // but the server has already replied. In this case, we don't 1620 // want to wait too long, and we want to return false so this 1621 // connection isn't re-used. 1622 select { 1623 case err := <-pc.writeErrCh: 1624 return err == nil 1625 case <-time.After(50 * time.Millisecond): 1626 return false 1627 } 1628 } 1629 } 1630 1631 // responseAndError is how the goroutine reading from an HTTP/1 server 1632 // communicates with the goroutine doing the RoundTrip. 1633 type responseAndError struct { 1634 res *Response // else use this response (see res method) 1635 err error 1636 } 1637 1638 type requestAndChan struct { 1639 req *Request 1640 ch chan responseAndError // unbuffered; always send in select on callerGone 1641 1642 // whether the Transport (as opposed to the user client code) 1643 // added the Accept-Encoding gzip header. If the Transport 1644 // set it, only then do we transparently decode the gzip. 1645 addedGzip bool 1646 1647 // Optional blocking chan for Expect: 100-continue (for send). 1648 // If the request has an "Expect: 100-continue" header and 1649 // the server responds 100 Continue, readLoop send a value 1650 // to writeLoop via this chan. 1651 continueCh chan<- struct{} 1652 1653 callerGone <-chan struct{} // closed when roundTrip caller has returned 1654 } 1655 1656 // A writeRequest is sent by the readLoop's goroutine to the 1657 // writeLoop's goroutine to write a request while the read loop 1658 // concurrently waits on both the write response and the server's 1659 // reply. 1660 type writeRequest struct { 1661 req *transportRequest 1662 ch chan<- error 1663 1664 // Optional blocking chan for Expect: 100-continue (for receive). 1665 // If not nil, writeLoop blocks sending request body until 1666 // it receives from this chan. 1667 continueCh <-chan struct{} 1668 } 1669 1670 type httpError struct { 1671 err string 1672 timeout bool 1673 } 1674 1675 func (e *httpError) Error() string { return e.err } 1676 func (e *httpError) Timeout() bool { return e.timeout } 1677 func (e *httpError) Temporary() bool { return true } 1678 1679 var errTimeout error = &httpError{err: "net/http: timeout awaiting response headers", timeout: true} 1680 var errRequestCanceled = errors.New("net/http: request canceled") 1681 var errRequestCanceledConn = errors.New("net/http: request canceled while waiting for connection") // TODO: unify? 1682 1683 func nop() {} 1684 1685 // testHooks. Always non-nil. 1686 var ( 1687 testHookEnterRoundTrip = nop 1688 testHookWaitResLoop = nop 1689 testHookRoundTripRetried = nop 1690 testHookPrePendingDial = nop 1691 testHookPostPendingDial = nop 1692 1693 testHookMu sync.Locker = fakeLocker{} // guards following 1694 testHookReadLoopBeforeNextRead = nop 1695 ) 1696 1697 func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err error) { 1698 testHookEnterRoundTrip() 1699 if !pc.t.replaceReqCanceler(req.Request, pc.cancelRequest) { 1700 pc.t.putOrCloseIdleConn(pc) 1701 return nil, errRequestCanceled 1702 } 1703 pc.mu.Lock() 1704 pc.numExpectedResponses++ 1705 headerFn := pc.mutateHeaderFunc 1706 pc.mu.Unlock() 1707 1708 if headerFn != nil { 1709 headerFn(req.extraHeaders()) 1710 } 1711 1712 // Ask for a compressed version if the caller didn't set their 1713 // own value for Accept-Encoding. We only attempt to 1714 // uncompress the gzip stream if we were the layer that 1715 // requested it. 1716 requestedGzip := false 1717 if !pc.t.DisableCompression && 1718 req.Header.Get("Accept-Encoding") == "" && 1719 req.Header.Get("Range") == "" && 1720 req.Method != "HEAD" { 1721 // Request gzip only, not deflate. Deflate is ambiguous and 1722 // not as universally supported anyway. 1723 // See: http://www.gzip.org/zlib/zlib_faq.html#faq38 1724 // 1725 // Note that we don't request this for HEAD requests, 1726 // due to a bug in nginx: 1727 // http://trac.nginx.org/nginx/ticket/358 1728 // https://golang.org/issue/5522 1729 // 1730 // We don't request gzip if the request is for a range, since 1731 // auto-decoding a portion of a gzipped document will just fail 1732 // anyway. See https://golang.org/issue/8923 1733 requestedGzip = true 1734 req.extraHeaders().Set("Accept-Encoding", "gzip") 1735 } 1736 1737 var continueCh chan struct{} 1738 if req.ProtoAtLeast(1, 1) && req.Body != nil && req.expectsContinue() { 1739 continueCh = make(chan struct{}, 1) 1740 } 1741 1742 if pc.t.DisableKeepAlives { 1743 req.extraHeaders().Set("Connection", "close") 1744 } 1745 1746 gone := make(chan struct{}) 1747 defer close(gone) 1748 1749 // Write the request concurrently with waiting for a response, 1750 // in case the server decides to reply before reading our full 1751 // request body. 1752 startBytesWritten := pc.nwrite 1753 writeErrCh := make(chan error, 1) 1754 pc.writech <- writeRequest{req, writeErrCh, continueCh} 1755 1756 resc := make(chan responseAndError) 1757 pc.reqch <- requestAndChan{ 1758 req: req.Request, 1759 ch: resc, 1760 addedGzip: requestedGzip, 1761 continueCh: continueCh, 1762 callerGone: gone, 1763 } 1764 1765 var re responseAndError 1766 var respHeaderTimer <-chan time.Time 1767 cancelChan := req.Request.Cancel 1768 WaitResponse: 1769 for { 1770 testHookWaitResLoop() 1771 select { 1772 case err := <-writeErrCh: 1773 if err != nil { 1774 if pc.isCanceled() { 1775 err = errRequestCanceled 1776 } 1777 re = responseAndError{err: err} 1778 pc.close(fmt.Errorf("write error: %v", err)) 1779 break WaitResponse 1780 } 1781 if d := pc.t.ResponseHeaderTimeout; d > 0 { 1782 timer := time.NewTimer(d) 1783 defer timer.Stop() // prevent leaks 1784 respHeaderTimer = timer.C 1785 } 1786 case <-pc.closech: 1787 re = responseAndError{err: pc.mapRoundTripErrorAfterClosed(startBytesWritten)} 1788 break WaitResponse 1789 case <-respHeaderTimer: 1790 pc.close(errTimeout) 1791 re = responseAndError{err: errTimeout} 1792 break WaitResponse 1793 case re = <-resc: 1794 re.err = pc.mapRoundTripErrorFromReadLoop(startBytesWritten, re.err) 1795 break WaitResponse 1796 case <-cancelChan: 1797 pc.t.CancelRequest(req.Request) 1798 cancelChan = nil 1799 case <-req.Context().Done(): 1800 pc.t.CancelRequest(req.Request) 1801 cancelChan = nil 1802 } 1803 } 1804 1805 if re.err != nil { 1806 pc.t.setReqCanceler(req.Request, nil) 1807 } 1808 if (re.res == nil) == (re.err == nil) { 1809 panic("internal error: exactly one of res or err should be set") 1810 } 1811 return re.res, re.err 1812 } 1813 1814 // markReused marks this connection as having been successfully used for a 1815 // request and response. 1816 func (pc *persistConn) markReused() { 1817 pc.mu.Lock() 1818 pc.reused = true 1819 pc.mu.Unlock() 1820 } 1821 1822 // close closes the underlying TCP connection and closes 1823 // the pc.closech channel. 1824 // 1825 // The provided err is only for testing and debugging; in normal 1826 // circumstances it should never be seen by users. 1827 func (pc *persistConn) close(err error) { 1828 pc.mu.Lock() 1829 defer pc.mu.Unlock() 1830 pc.closeLocked(err) 1831 } 1832 1833 func (pc *persistConn) closeLocked(err error) { 1834 if err == nil { 1835 panic("nil error") 1836 } 1837 pc.broken = true 1838 if pc.closed == nil { 1839 pc.closed = err 1840 if pc.alt != nil { 1841 // Do nothing; can only get here via getConn's 1842 // handlePendingDial's putOrCloseIdleConn when 1843 // it turns out the abandoned connection in 1844 // flight ended up negotiating an alternate 1845 // protocol. We don't use the connection 1846 // freelist for http2. That's done by the 1847 // alternate protocol's RoundTripper. 1848 } else { 1849 pc.conn.Close() 1850 close(pc.closech) 1851 } 1852 } 1853 pc.mutateHeaderFunc = nil 1854 } 1855 1856 var portMap = map[string]string{ 1857 "http": "80", 1858 "https": "443", 1859 } 1860 1861 // canonicalAddr returns url.Host but always with a ":port" suffix 1862 func canonicalAddr(url *url.URL) string { 1863 addr := url.Host 1864 if !hasPort(addr) { 1865 return addr + ":" + portMap[url.Scheme] 1866 } 1867 return addr 1868 } 1869 1870 // bodyEOFSignal is used by the HTTP/1 transport when reading response 1871 // bodies to make sure we see the end of a response body before 1872 // proceeding and reading on the connection again. 1873 // 1874 // It wraps a ReadCloser but runs fn (if non-nil) at most 1875 // once, right before its final (error-producing) Read or Close call 1876 // returns. fn should return the new error to return from Read or Close. 1877 // 1878 // If earlyCloseFn is non-nil and Close is called before io.EOF is 1879 // seen, earlyCloseFn is called instead of fn, and its return value is 1880 // the return value from Close. 1881 type bodyEOFSignal struct { 1882 body io.ReadCloser 1883 mu sync.Mutex // guards following 4 fields 1884 closed bool // whether Close has been called 1885 rerr error // sticky Read error 1886 fn func(error) error // err will be nil on Read io.EOF 1887 earlyCloseFn func() error // optional alt Close func used if io.EOF not seen 1888 } 1889 1890 var errReadOnClosedResBody = errors.New("http: read on closed response body") 1891 1892 func (es *bodyEOFSignal) Read(p []byte) (n int, err error) { 1893 es.mu.Lock() 1894 closed, rerr := es.closed, es.rerr 1895 es.mu.Unlock() 1896 if closed { 1897 return 0, errReadOnClosedResBody 1898 } 1899 if rerr != nil { 1900 return 0, rerr 1901 } 1902 1903 n, err = es.body.Read(p) 1904 if err != nil { 1905 es.mu.Lock() 1906 defer es.mu.Unlock() 1907 if es.rerr == nil { 1908 es.rerr = err 1909 } 1910 err = es.condfn(err) 1911 } 1912 return 1913 } 1914 1915 func (es *bodyEOFSignal) Close() error { 1916 es.mu.Lock() 1917 defer es.mu.Unlock() 1918 if es.closed { 1919 return nil 1920 } 1921 es.closed = true 1922 if es.earlyCloseFn != nil && es.rerr != io.EOF { 1923 return es.earlyCloseFn() 1924 } 1925 err := es.body.Close() 1926 return es.condfn(err) 1927 } 1928 1929 // caller must hold es.mu. 1930 func (es *bodyEOFSignal) condfn(err error) error { 1931 if es.fn == nil { 1932 return err 1933 } 1934 err = es.fn(err) 1935 es.fn = nil 1936 return err 1937 } 1938 1939 // gzipReader wraps a response body so it can lazily 1940 // call gzip.NewReader on the first call to Read 1941 type gzipReader struct { 1942 body *bodyEOFSignal // underlying HTTP/1 response body framing 1943 zr *gzip.Reader // lazily-initialized gzip reader 1944 zerr error // any error from gzip.NewReader; sticky 1945 } 1946 1947 func (gz *gzipReader) Read(p []byte) (n int, err error) { 1948 if gz.zr == nil { 1949 if gz.zerr == nil { 1950 gz.zr, gz.zerr = gzip.NewReader(gz.body) 1951 } 1952 if gz.zerr != nil { 1953 return 0, gz.zerr 1954 } 1955 } 1956 1957 gz.body.mu.Lock() 1958 if gz.body.closed { 1959 err = errReadOnClosedResBody 1960 } 1961 gz.body.mu.Unlock() 1962 1963 if err != nil { 1964 return 0, err 1965 } 1966 return gz.zr.Read(p) 1967 } 1968 1969 func (gz *gzipReader) Close() error { 1970 return gz.body.Close() 1971 } 1972 1973 type readerAndCloser struct { 1974 io.Reader 1975 io.Closer 1976 } 1977 1978 type tlsHandshakeTimeoutError struct{} 1979 1980 func (tlsHandshakeTimeoutError) Timeout() bool { return true } 1981 func (tlsHandshakeTimeoutError) Temporary() bool { return true } 1982 func (tlsHandshakeTimeoutError) Error() string { return "net/http: TLS handshake timeout" } 1983 1984 // fakeLocker is a sync.Locker which does nothing. It's used to guard 1985 // test-only fields when not under test, to avoid runtime atomic 1986 // overhead. 1987 type fakeLocker struct{} 1988 1989 func (fakeLocker) Lock() {} 1990 func (fakeLocker) Unlock() {} 1991 1992 // cloneTLSConfig returns a shallow clone of the exported 1993 // fields of cfg, ignoring the unexported sync.Once, which 1994 // contains a mutex and must not be copied. 1995 // 1996 // The cfg must not be in active use by tls.Server, or else 1997 // there can still be a race with tls.Server updating SessionTicketKey 1998 // and our copying it, and also a race with the server setting 1999 // SessionTicketsDisabled=false on failure to set the random 2000 // ticket key. 2001 // 2002 // If cfg is nil, a new zero tls.Config is returned. 2003 func cloneTLSConfig(cfg *tls.Config) *tls.Config { 2004 if cfg == nil { 2005 return &tls.Config{} 2006 } 2007 return &tls.Config{ 2008 Rand: cfg.Rand, 2009 Time: cfg.Time, 2010 Certificates: cfg.Certificates, 2011 NameToCertificate: cfg.NameToCertificate, 2012 GetCertificate: cfg.GetCertificate, 2013 RootCAs: cfg.RootCAs, 2014 NextProtos: cfg.NextProtos, 2015 ServerName: cfg.ServerName, 2016 ClientAuth: cfg.ClientAuth, 2017 ClientCAs: cfg.ClientCAs, 2018 InsecureSkipVerify: cfg.InsecureSkipVerify, 2019 CipherSuites: cfg.CipherSuites, 2020 PreferServerCipherSuites: cfg.PreferServerCipherSuites, 2021 SessionTicketsDisabled: cfg.SessionTicketsDisabled, 2022 SessionTicketKey: cfg.SessionTicketKey, 2023 ClientSessionCache: cfg.ClientSessionCache, 2024 MinVersion: cfg.MinVersion, 2025 MaxVersion: cfg.MaxVersion, 2026 CurvePreferences: cfg.CurvePreferences, 2027 DynamicRecordSizingDisabled: cfg.DynamicRecordSizingDisabled, 2028 Renegotiation: cfg.Renegotiation, 2029 } 2030 } 2031 2032 // cloneTLSClientConfig is like cloneTLSConfig but omits 2033 // the fields SessionTicketsDisabled and SessionTicketKey. 2034 // This makes it safe to call cloneTLSClientConfig on a config 2035 // in active use by a server. 2036 func cloneTLSClientConfig(cfg *tls.Config) *tls.Config { 2037 if cfg == nil { 2038 return &tls.Config{} 2039 } 2040 return &tls.Config{ 2041 Rand: cfg.Rand, 2042 Time: cfg.Time, 2043 Certificates: cfg.Certificates, 2044 NameToCertificate: cfg.NameToCertificate, 2045 GetCertificate: cfg.GetCertificate, 2046 RootCAs: cfg.RootCAs, 2047 NextProtos: cfg.NextProtos, 2048 ServerName: cfg.ServerName, 2049 ClientAuth: cfg.ClientAuth, 2050 ClientCAs: cfg.ClientCAs, 2051 InsecureSkipVerify: cfg.InsecureSkipVerify, 2052 CipherSuites: cfg.CipherSuites, 2053 PreferServerCipherSuites: cfg.PreferServerCipherSuites, 2054 ClientSessionCache: cfg.ClientSessionCache, 2055 MinVersion: cfg.MinVersion, 2056 MaxVersion: cfg.MaxVersion, 2057 CurvePreferences: cfg.CurvePreferences, 2058 DynamicRecordSizingDisabled: cfg.DynamicRecordSizingDisabled, 2059 Renegotiation: cfg.Renegotiation, 2060 } 2061 } 2062 2063 type connLRU struct { 2064 ll *list.List // list.Element.Value type is of *persistConn 2065 m map[*persistConn]*list.Element 2066 } 2067 2068 // add adds pc to the head of the linked list. 2069 func (cl *connLRU) add(pc *persistConn) { 2070 if cl.ll == nil { 2071 cl.ll = list.New() 2072 cl.m = make(map[*persistConn]*list.Element) 2073 } 2074 ele := cl.ll.PushFront(pc) 2075 if _, ok := cl.m[pc]; ok { 2076 panic("persistConn was already in LRU") 2077 } 2078 cl.m[pc] = ele 2079 } 2080 2081 func (cl *connLRU) removeOldest() *persistConn { 2082 ele := cl.ll.Back() 2083 pc := ele.Value.(*persistConn) 2084 cl.ll.Remove(ele) 2085 delete(cl.m, pc) 2086 return pc 2087 } 2088 2089 // remove removes pc from cl. 2090 func (cl *connLRU) remove(pc *persistConn) { 2091 if ele, ok := cl.m[pc]; ok { 2092 cl.ll.Remove(ele) 2093 delete(cl.m, pc) 2094 } 2095 } 2096 2097 // len returns the number of items in the cache. 2098 func (cl *connLRU) len() int { 2099 return len(cl.m) 2100 }