github.com/letsencrypt/go@v0.0.0-20160714163537-4054769a31f6/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 v.pc != nil { 849 if trace != nil && trace.GotConn != nil && v.pc.alt == nil { 850 trace.GotConn(httptrace.GotConnInfo{Conn: v.pc.conn}) 851 } 852 return v.pc, nil 853 } 854 // Our dial failed. See why to return a nicer error 855 // value. 856 select { 857 case <-req.Cancel: 858 case <-req.Context().Done(): 859 case <-cancelc: 860 default: 861 // It wasn't an error due to cancelation, so 862 // return the original error message: 863 return nil, v.err 864 } 865 // It was an error due to cancelation, so prioritize that 866 // error value. (Issue 16049) 867 return nil, errRequestCanceledConn 868 case pc := <-idleConnCh: 869 // Another request finished first and its net.Conn 870 // became available before our dial. Or somebody 871 // else's dial that they didn't use. 872 // But our dial is still going, so give it away 873 // when it finishes: 874 handlePendingDial() 875 if trace != nil && trace.GotConn != nil { 876 trace.GotConn(httptrace.GotConnInfo{Conn: pc.conn, Reused: pc.isReused()}) 877 } 878 return pc, nil 879 case <-req.Cancel: 880 handlePendingDial() 881 return nil, errRequestCanceledConn 882 case <-req.Context().Done(): 883 handlePendingDial() 884 return nil, errRequestCanceledConn 885 case <-cancelc: 886 handlePendingDial() 887 return nil, errRequestCanceledConn 888 } 889 } 890 891 func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (*persistConn, error) { 892 pconn := &persistConn{ 893 t: t, 894 cacheKey: cm.key(), 895 reqch: make(chan requestAndChan, 1), 896 writech: make(chan writeRequest, 1), 897 closech: make(chan struct{}), 898 writeErrCh: make(chan error, 1), 899 writeLoopDone: make(chan struct{}), 900 } 901 tlsDial := t.DialTLS != nil && cm.targetScheme == "https" && cm.proxyURL == nil 902 if tlsDial { 903 var err error 904 pconn.conn, err = t.DialTLS("tcp", cm.addr()) 905 if err != nil { 906 return nil, err 907 } 908 if pconn.conn == nil { 909 return nil, errors.New("net/http: Transport.DialTLS returned (nil, nil)") 910 } 911 if tc, ok := pconn.conn.(*tls.Conn); ok { 912 // Handshake here, in case DialTLS didn't. TLSNextProto below 913 // depends on it for knowing the connection state. 914 if err := tc.Handshake(); err != nil { 915 go pconn.conn.Close() 916 return nil, err 917 } 918 cs := tc.ConnectionState() 919 pconn.tlsState = &cs 920 } 921 } else { 922 conn, err := t.dial(ctx, "tcp", cm.addr()) 923 if err != nil { 924 if cm.proxyURL != nil { 925 err = fmt.Errorf("http: error connecting to proxy %s: %v", cm.proxyURL, err) 926 } 927 return nil, err 928 } 929 pconn.conn = conn 930 } 931 932 // Proxy setup. 933 switch { 934 case cm.proxyURL == nil: 935 // Do nothing. Not using a proxy. 936 case cm.targetScheme == "http": 937 pconn.isProxy = true 938 if pa := cm.proxyAuth(); pa != "" { 939 pconn.mutateHeaderFunc = func(h Header) { 940 h.Set("Proxy-Authorization", pa) 941 } 942 } 943 case cm.targetScheme == "https": 944 conn := pconn.conn 945 connectReq := &Request{ 946 Method: "CONNECT", 947 URL: &url.URL{Opaque: cm.targetAddr}, 948 Host: cm.targetAddr, 949 Header: make(Header), 950 } 951 if pa := cm.proxyAuth(); pa != "" { 952 connectReq.Header.Set("Proxy-Authorization", pa) 953 } 954 connectReq.Write(conn) 955 956 // Read response. 957 // Okay to use and discard buffered reader here, because 958 // TLS server will not speak until spoken to. 959 br := bufio.NewReader(conn) 960 resp, err := ReadResponse(br, connectReq) 961 if err != nil { 962 conn.Close() 963 return nil, err 964 } 965 if resp.StatusCode != 200 { 966 f := strings.SplitN(resp.Status, " ", 2) 967 conn.Close() 968 return nil, errors.New(f[1]) 969 } 970 } 971 972 if cm.targetScheme == "https" && !tlsDial { 973 // Initiate TLS and check remote host name against certificate. 974 cfg := cloneTLSClientConfig(t.TLSClientConfig) 975 if cfg.ServerName == "" { 976 cfg.ServerName = cm.tlsHost() 977 } 978 plainConn := pconn.conn 979 tlsConn := tls.Client(plainConn, cfg) 980 errc := make(chan error, 2) 981 var timer *time.Timer // for canceling TLS handshake 982 if d := t.TLSHandshakeTimeout; d != 0 { 983 timer = time.AfterFunc(d, func() { 984 errc <- tlsHandshakeTimeoutError{} 985 }) 986 } 987 go func() { 988 err := tlsConn.Handshake() 989 if timer != nil { 990 timer.Stop() 991 } 992 errc <- err 993 }() 994 if err := <-errc; err != nil { 995 plainConn.Close() 996 return nil, err 997 } 998 if !cfg.InsecureSkipVerify { 999 if err := tlsConn.VerifyHostname(cfg.ServerName); err != nil { 1000 plainConn.Close() 1001 return nil, err 1002 } 1003 } 1004 cs := tlsConn.ConnectionState() 1005 pconn.tlsState = &cs 1006 pconn.conn = tlsConn 1007 } 1008 1009 if s := pconn.tlsState; s != nil && s.NegotiatedProtocolIsMutual && s.NegotiatedProtocol != "" { 1010 if next, ok := t.TLSNextProto[s.NegotiatedProtocol]; ok { 1011 return &persistConn{alt: next(cm.targetAddr, pconn.conn.(*tls.Conn))}, nil 1012 } 1013 } 1014 1015 pconn.br = bufio.NewReader(pconn) 1016 pconn.bw = bufio.NewWriter(persistConnWriter{pconn}) 1017 go pconn.readLoop() 1018 go pconn.writeLoop() 1019 return pconn, nil 1020 } 1021 1022 // persistConnWriter is the io.Writer written to by pc.bw. 1023 // It accumulates the number of bytes written to the underlying conn, 1024 // so the retry logic can determine whether any bytes made it across 1025 // the wire. 1026 // This is exactly 1 pointer field wide so it can go into an interface 1027 // without allocation. 1028 type persistConnWriter struct { 1029 pc *persistConn 1030 } 1031 1032 func (w persistConnWriter) Write(p []byte) (n int, err error) { 1033 n, err = w.pc.conn.Write(p) 1034 w.pc.nwrite += int64(n) 1035 return 1036 } 1037 1038 // useProxy reports whether requests to addr should use a proxy, 1039 // according to the NO_PROXY or no_proxy environment variable. 1040 // addr is always a canonicalAddr with a host and port. 1041 func useProxy(addr string) bool { 1042 if len(addr) == 0 { 1043 return true 1044 } 1045 host, _, err := net.SplitHostPort(addr) 1046 if err != nil { 1047 return false 1048 } 1049 if host == "localhost" { 1050 return false 1051 } 1052 if ip := net.ParseIP(host); ip != nil { 1053 if ip.IsLoopback() { 1054 return false 1055 } 1056 } 1057 1058 no_proxy := noProxyEnv.Get() 1059 if no_proxy == "*" { 1060 return false 1061 } 1062 1063 addr = strings.ToLower(strings.TrimSpace(addr)) 1064 if hasPort(addr) { 1065 addr = addr[:strings.LastIndex(addr, ":")] 1066 } 1067 1068 for _, p := range strings.Split(no_proxy, ",") { 1069 p = strings.ToLower(strings.TrimSpace(p)) 1070 if len(p) == 0 { 1071 continue 1072 } 1073 if hasPort(p) { 1074 p = p[:strings.LastIndex(p, ":")] 1075 } 1076 if addr == p { 1077 return false 1078 } 1079 if p[0] == '.' && (strings.HasSuffix(addr, p) || addr == p[1:]) { 1080 // no_proxy ".foo.com" matches "bar.foo.com" or "foo.com" 1081 return false 1082 } 1083 if p[0] != '.' && strings.HasSuffix(addr, p) && addr[len(addr)-len(p)-1] == '.' { 1084 // no_proxy "foo.com" matches "bar.foo.com" 1085 return false 1086 } 1087 } 1088 return true 1089 } 1090 1091 // connectMethod is the map key (in its String form) for keeping persistent 1092 // TCP connections alive for subsequent HTTP requests. 1093 // 1094 // A connect method may be of the following types: 1095 // 1096 // Cache key form Description 1097 // ----------------- ------------------------- 1098 // |http|foo.com http directly to server, no proxy 1099 // |https|foo.com https directly to server, no proxy 1100 // http://proxy.com|https|foo.com http to proxy, then CONNECT to foo.com 1101 // http://proxy.com|http http to proxy, http to anywhere after that 1102 // 1103 // Note: no support to https to the proxy yet. 1104 // 1105 type connectMethod struct { 1106 proxyURL *url.URL // nil for no proxy, else full proxy URL 1107 targetScheme string // "http" or "https" 1108 targetAddr string // Not used if proxy + http targetScheme (4th example in table) 1109 } 1110 1111 func (cm *connectMethod) key() connectMethodKey { 1112 proxyStr := "" 1113 targetAddr := cm.targetAddr 1114 if cm.proxyURL != nil { 1115 proxyStr = cm.proxyURL.String() 1116 if cm.targetScheme == "http" { 1117 targetAddr = "" 1118 } 1119 } 1120 return connectMethodKey{ 1121 proxy: proxyStr, 1122 scheme: cm.targetScheme, 1123 addr: targetAddr, 1124 } 1125 } 1126 1127 // addr returns the first hop "host:port" to which we need to TCP connect. 1128 func (cm *connectMethod) addr() string { 1129 if cm.proxyURL != nil { 1130 return canonicalAddr(cm.proxyURL) 1131 } 1132 return cm.targetAddr 1133 } 1134 1135 // tlsHost returns the host name to match against the peer's 1136 // TLS certificate. 1137 func (cm *connectMethod) tlsHost() string { 1138 h := cm.targetAddr 1139 if hasPort(h) { 1140 h = h[:strings.LastIndex(h, ":")] 1141 } 1142 return h 1143 } 1144 1145 // connectMethodKey is the map key version of connectMethod, with a 1146 // stringified proxy URL (or the empty string) instead of a pointer to 1147 // a URL. 1148 type connectMethodKey struct { 1149 proxy, scheme, addr string 1150 } 1151 1152 func (k connectMethodKey) String() string { 1153 // Only used by tests. 1154 return fmt.Sprintf("%s|%s|%s", k.proxy, k.scheme, k.addr) 1155 } 1156 1157 // persistConn wraps a connection, usually a persistent one 1158 // (but may be used for non-keep-alive requests as well) 1159 type persistConn struct { 1160 // alt optionally specifies the TLS NextProto RoundTripper. 1161 // This is used for HTTP/2 today and future protocols later. 1162 // If it's non-nil, the rest of the fields are unused. 1163 alt RoundTripper 1164 1165 t *Transport 1166 cacheKey connectMethodKey 1167 conn net.Conn 1168 tlsState *tls.ConnectionState 1169 br *bufio.Reader // from conn 1170 bw *bufio.Writer // to conn 1171 nwrite int64 // bytes written 1172 reqch chan requestAndChan // written by roundTrip; read by readLoop 1173 writech chan writeRequest // written by roundTrip; read by writeLoop 1174 closech chan struct{} // closed when conn closed 1175 isProxy bool 1176 sawEOF bool // whether we've seen EOF from conn; owned by readLoop 1177 readLimit int64 // bytes allowed to be read; owned by readLoop 1178 // writeErrCh passes the request write error (usually nil) 1179 // from the writeLoop goroutine to the readLoop which passes 1180 // it off to the res.Body reader, which then uses it to decide 1181 // whether or not a connection can be reused. Issue 7569. 1182 writeErrCh chan error 1183 1184 writeLoopDone chan struct{} // closed when write loop ends 1185 1186 // Both guarded by Transport.idleMu: 1187 idleAt time.Time // time it last become idle 1188 idleTimer *time.Timer // holding an AfterFunc to close it 1189 1190 mu sync.Mutex // guards following fields 1191 numExpectedResponses int 1192 closed error // set non-nil when conn is closed, before closech is closed 1193 broken bool // an error has happened on this connection; marked broken so it's not reused. 1194 canceled bool // whether this conn was broken due a CancelRequest 1195 reused bool // whether conn has had successful request/response and is being reused. 1196 // mutateHeaderFunc is an optional func to modify extra 1197 // headers on each outbound request before it's written. (the 1198 // original Request given to RoundTrip is not modified) 1199 mutateHeaderFunc func(Header) 1200 } 1201 1202 func (pc *persistConn) maxHeaderResponseSize() int64 { 1203 if v := pc.t.MaxResponseHeaderBytes; v != 0 { 1204 return v 1205 } 1206 return 10 << 20 // conservative default; same as http2 1207 } 1208 1209 func (pc *persistConn) Read(p []byte) (n int, err error) { 1210 if pc.readLimit <= 0 { 1211 return 0, fmt.Errorf("read limit of %d bytes exhausted", pc.maxHeaderResponseSize()) 1212 } 1213 if int64(len(p)) > pc.readLimit { 1214 p = p[:pc.readLimit] 1215 } 1216 n, err = pc.conn.Read(p) 1217 if err == io.EOF { 1218 pc.sawEOF = true 1219 } 1220 pc.readLimit -= int64(n) 1221 return 1222 } 1223 1224 // isBroken reports whether this connection is in a known broken state. 1225 func (pc *persistConn) isBroken() bool { 1226 pc.mu.Lock() 1227 b := pc.closed != nil 1228 pc.mu.Unlock() 1229 return b 1230 } 1231 1232 // isCanceled reports whether this connection was closed due to CancelRequest. 1233 func (pc *persistConn) isCanceled() bool { 1234 pc.mu.Lock() 1235 defer pc.mu.Unlock() 1236 return pc.canceled 1237 } 1238 1239 // isReused reports whether this connection is in a known broken state. 1240 func (pc *persistConn) isReused() bool { 1241 pc.mu.Lock() 1242 r := pc.reused 1243 pc.mu.Unlock() 1244 return r 1245 } 1246 1247 func (pc *persistConn) gotIdleConnTrace(idleAt time.Time) (t httptrace.GotConnInfo) { 1248 pc.mu.Lock() 1249 defer pc.mu.Unlock() 1250 t.Reused = pc.reused 1251 t.Conn = pc.conn 1252 t.WasIdle = true 1253 if !idleAt.IsZero() { 1254 t.IdleTime = time.Since(idleAt) 1255 } 1256 return 1257 } 1258 1259 func (pc *persistConn) cancelRequest() { 1260 pc.mu.Lock() 1261 defer pc.mu.Unlock() 1262 pc.canceled = true 1263 pc.closeLocked(errRequestCanceled) 1264 } 1265 1266 // closeConnIfStillIdle closes the connection if it's still sitting idle. 1267 // This is what's called by the persistConn's idleTimer, and is run in its 1268 // own goroutine. 1269 func (pc *persistConn) closeConnIfStillIdle() { 1270 t := pc.t 1271 t.idleMu.Lock() 1272 defer t.idleMu.Unlock() 1273 if _, ok := t.idleLRU.m[pc]; !ok { 1274 // Not idle. 1275 return 1276 } 1277 t.removeIdleConnLocked(pc) 1278 pc.close(errIdleConnTimeout) 1279 } 1280 1281 // mapRoundTripErrorFromReadLoop maps the provided readLoop error into 1282 // the error value that should be returned from persistConn.roundTrip. 1283 // 1284 // The startBytesWritten value should be the value of pc.nwrite before the roundTrip 1285 // started writing the request. 1286 func (pc *persistConn) mapRoundTripErrorFromReadLoop(startBytesWritten int64, err error) (out error) { 1287 if err == nil { 1288 return nil 1289 } 1290 if pc.isCanceled() { 1291 return errRequestCanceled 1292 } 1293 if err == errServerClosedIdle || err == errServerClosedConn { 1294 return err 1295 } 1296 if pc.isBroken() { 1297 <-pc.writeLoopDone 1298 if pc.nwrite == startBytesWritten { 1299 return nothingWrittenError{err} 1300 } 1301 } 1302 return err 1303 } 1304 1305 // mapRoundTripErrorAfterClosed returns the error value to be propagated 1306 // up to Transport.RoundTrip method when persistConn.roundTrip sees 1307 // its pc.closech channel close, indicating the persistConn is dead. 1308 // (after closech is closed, pc.closed is valid). 1309 func (pc *persistConn) mapRoundTripErrorAfterClosed(startBytesWritten int64) error { 1310 if pc.isCanceled() { 1311 return errRequestCanceled 1312 } 1313 err := pc.closed 1314 if err == errServerClosedIdle || err == errServerClosedConn { 1315 // Don't decorate 1316 return err 1317 } 1318 1319 // Wait for the writeLoop goroutine to terminated, and then 1320 // see if we actually managed to write anything. If not, we 1321 // can retry the request. 1322 <-pc.writeLoopDone 1323 if pc.nwrite == startBytesWritten { 1324 return nothingWrittenError{err} 1325 } 1326 1327 return fmt.Errorf("net/http: HTTP/1.x transport connection broken: %v", err) 1328 1329 } 1330 1331 func (pc *persistConn) readLoop() { 1332 closeErr := errReadLoopExiting // default value, if not changed below 1333 defer func() { 1334 pc.close(closeErr) 1335 pc.t.removeIdleConn(pc) 1336 }() 1337 1338 tryPutIdleConn := func(trace *httptrace.ClientTrace) bool { 1339 if err := pc.t.tryPutIdleConn(pc); err != nil { 1340 closeErr = err 1341 if trace != nil && trace.PutIdleConn != nil && err != errKeepAlivesDisabled { 1342 trace.PutIdleConn(err) 1343 } 1344 return false 1345 } 1346 if trace != nil && trace.PutIdleConn != nil { 1347 trace.PutIdleConn(nil) 1348 } 1349 return true 1350 } 1351 1352 // eofc is used to block caller goroutines reading from Response.Body 1353 // at EOF until this goroutines has (potentially) added the connection 1354 // back to the idle pool. 1355 eofc := make(chan struct{}) 1356 defer close(eofc) // unblock reader on errors 1357 1358 // Read this once, before loop starts. (to avoid races in tests) 1359 testHookMu.Lock() 1360 testHookReadLoopBeforeNextRead := testHookReadLoopBeforeNextRead 1361 testHookMu.Unlock() 1362 1363 alive := true 1364 for alive { 1365 pc.readLimit = pc.maxHeaderResponseSize() 1366 _, err := pc.br.Peek(1) 1367 1368 pc.mu.Lock() 1369 if pc.numExpectedResponses == 0 { 1370 pc.readLoopPeekFailLocked(err) 1371 pc.mu.Unlock() 1372 return 1373 } 1374 pc.mu.Unlock() 1375 1376 rc := <-pc.reqch 1377 trace := httptrace.ContextClientTrace(rc.req.Context()) 1378 1379 var resp *Response 1380 if err == nil { 1381 resp, err = pc.readResponse(rc, trace) 1382 } else { 1383 err = errServerClosedConn 1384 closeErr = err 1385 } 1386 1387 if err != nil { 1388 if pc.readLimit <= 0 { 1389 err = fmt.Errorf("net/http: server response headers exceeded %d bytes; aborted", pc.maxHeaderResponseSize()) 1390 } 1391 1392 // If we won't be able to retry this request later (from the 1393 // roundTrip goroutine), mark it as done now. 1394 // BEFORE the send on rc.ch, as the client might re-use the 1395 // same *Request pointer, and we don't want to set call 1396 // t.setReqCanceler from this persistConn while the Transport 1397 // potentially spins up a different persistConn for the 1398 // caller's subsequent request. 1399 if !pc.shouldRetryRequest(rc.req, err) { 1400 pc.t.setReqCanceler(rc.req, nil) 1401 } 1402 select { 1403 case rc.ch <- responseAndError{err: err}: 1404 case <-rc.callerGone: 1405 return 1406 } 1407 return 1408 } 1409 pc.readLimit = maxInt64 // effictively no limit for response bodies 1410 1411 pc.mu.Lock() 1412 pc.numExpectedResponses-- 1413 pc.mu.Unlock() 1414 1415 hasBody := rc.req.Method != "HEAD" && resp.ContentLength != 0 1416 1417 if resp.Close || rc.req.Close || resp.StatusCode <= 199 { 1418 // Don't do keep-alive on error if either party requested a close 1419 // or we get an unexpected informational (1xx) response. 1420 // StatusCode 100 is already handled above. 1421 alive = false 1422 } 1423 1424 if !hasBody { 1425 pc.t.setReqCanceler(rc.req, nil) 1426 1427 // Put the idle conn back into the pool before we send the response 1428 // so if they process it quickly and make another request, they'll 1429 // get this same conn. But we use the unbuffered channel 'rc' 1430 // to guarantee that persistConn.roundTrip got out of its select 1431 // potentially waiting for this persistConn to close. 1432 // but after 1433 alive = alive && 1434 !pc.sawEOF && 1435 pc.wroteRequest() && 1436 tryPutIdleConn(trace) 1437 1438 select { 1439 case rc.ch <- responseAndError{res: resp}: 1440 case <-rc.callerGone: 1441 return 1442 } 1443 1444 // Now that they've read from the unbuffered channel, they're safely 1445 // out of the select that also waits on this goroutine to die, so 1446 // we're allowed to exit now if needed (if alive is false) 1447 testHookReadLoopBeforeNextRead() 1448 continue 1449 } 1450 1451 waitForBodyRead := make(chan bool, 2) 1452 body := &bodyEOFSignal{ 1453 body: resp.Body, 1454 earlyCloseFn: func() error { 1455 waitForBodyRead <- false 1456 return nil 1457 1458 }, 1459 fn: func(err error) error { 1460 isEOF := err == io.EOF 1461 waitForBodyRead <- isEOF 1462 if isEOF { 1463 <-eofc // see comment above eofc declaration 1464 } else if err != nil && pc.isCanceled() { 1465 return errRequestCanceled 1466 } 1467 return err 1468 }, 1469 } 1470 1471 resp.Body = body 1472 if rc.addedGzip && resp.Header.Get("Content-Encoding") == "gzip" { 1473 resp.Body = &gzipReader{body: body} 1474 resp.Header.Del("Content-Encoding") 1475 resp.Header.Del("Content-Length") 1476 resp.ContentLength = -1 1477 resp.Uncompressed = true 1478 } 1479 1480 select { 1481 case rc.ch <- responseAndError{res: resp}: 1482 case <-rc.callerGone: 1483 return 1484 } 1485 1486 // Before looping back to the top of this function and peeking on 1487 // the bufio.Reader, wait for the caller goroutine to finish 1488 // reading the response body. (or for cancelation or death) 1489 select { 1490 case bodyEOF := <-waitForBodyRead: 1491 pc.t.setReqCanceler(rc.req, nil) // before pc might return to idle pool 1492 alive = alive && 1493 bodyEOF && 1494 !pc.sawEOF && 1495 pc.wroteRequest() && 1496 tryPutIdleConn(trace) 1497 if bodyEOF { 1498 eofc <- struct{}{} 1499 } 1500 case <-rc.req.Cancel: 1501 alive = false 1502 pc.t.CancelRequest(rc.req) 1503 case <-rc.req.Context().Done(): 1504 alive = false 1505 pc.t.CancelRequest(rc.req) 1506 case <-pc.closech: 1507 alive = false 1508 } 1509 1510 testHookReadLoopBeforeNextRead() 1511 } 1512 } 1513 1514 func (pc *persistConn) readLoopPeekFailLocked(peekErr error) { 1515 if pc.closed != nil { 1516 return 1517 } 1518 if n := pc.br.Buffered(); n > 0 { 1519 buf, _ := pc.br.Peek(n) 1520 log.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v", buf, peekErr) 1521 } 1522 if peekErr == io.EOF { 1523 // common case. 1524 pc.closeLocked(errServerClosedIdle) 1525 } else { 1526 pc.closeLocked(fmt.Errorf("readLoopPeekFailLocked: %v", peekErr)) 1527 } 1528 } 1529 1530 // readResponse reads an HTTP response (or two, in the case of "Expect: 1531 // 100-continue") from the server. It returns the final non-100 one. 1532 // trace is optional. 1533 func (pc *persistConn) readResponse(rc requestAndChan, trace *httptrace.ClientTrace) (resp *Response, err error) { 1534 if trace != nil && trace.GotFirstResponseByte != nil { 1535 if peek, err := pc.br.Peek(1); err == nil && len(peek) == 1 { 1536 trace.GotFirstResponseByte() 1537 } 1538 } 1539 resp, err = ReadResponse(pc.br, rc.req) 1540 if err != nil { 1541 return 1542 } 1543 if rc.continueCh != nil { 1544 if resp.StatusCode == 100 { 1545 if trace != nil && trace.Got100Continue != nil { 1546 trace.Got100Continue() 1547 } 1548 rc.continueCh <- struct{}{} 1549 } else { 1550 close(rc.continueCh) 1551 } 1552 } 1553 if resp.StatusCode == 100 { 1554 pc.readLimit = pc.maxHeaderResponseSize() // reset the limit 1555 resp, err = ReadResponse(pc.br, rc.req) 1556 if err != nil { 1557 return 1558 } 1559 } 1560 resp.TLS = pc.tlsState 1561 return 1562 } 1563 1564 // waitForContinue returns the function to block until 1565 // any response, timeout or connection close. After any of them, 1566 // the function returns a bool which indicates if the body should be sent. 1567 func (pc *persistConn) waitForContinue(continueCh <-chan struct{}) func() bool { 1568 if continueCh == nil { 1569 return nil 1570 } 1571 return func() bool { 1572 timer := time.NewTimer(pc.t.ExpectContinueTimeout) 1573 defer timer.Stop() 1574 1575 select { 1576 case _, ok := <-continueCh: 1577 return ok 1578 case <-timer.C: 1579 return true 1580 case <-pc.closech: 1581 return false 1582 } 1583 } 1584 } 1585 1586 // nothingWrittenError wraps a write errors which ended up writing zero bytes. 1587 type nothingWrittenError struct { 1588 error 1589 } 1590 1591 func (pc *persistConn) writeLoop() { 1592 defer close(pc.writeLoopDone) 1593 for { 1594 select { 1595 case wr := <-pc.writech: 1596 startBytesWritten := pc.nwrite 1597 err := wr.req.Request.write(pc.bw, pc.isProxy, wr.req.extra, pc.waitForContinue(wr.continueCh)) 1598 if err == nil { 1599 err = pc.bw.Flush() 1600 } 1601 if err != nil { 1602 wr.req.Request.closeBody() 1603 if pc.nwrite == startBytesWritten { 1604 err = nothingWrittenError{err} 1605 } 1606 } 1607 pc.writeErrCh <- err // to the body reader, which might recycle us 1608 wr.ch <- err // to the roundTrip function 1609 if err != nil { 1610 pc.close(err) 1611 return 1612 } 1613 case <-pc.closech: 1614 return 1615 } 1616 } 1617 } 1618 1619 // wroteRequest is a check before recycling a connection that the previous write 1620 // (from writeLoop above) happened and was successful. 1621 func (pc *persistConn) wroteRequest() bool { 1622 select { 1623 case err := <-pc.writeErrCh: 1624 // Common case: the write happened well before the response, so 1625 // avoid creating a timer. 1626 return err == nil 1627 default: 1628 // Rare case: the request was written in writeLoop above but 1629 // before it could send to pc.writeErrCh, the reader read it 1630 // all, processed it, and called us here. In this case, give the 1631 // write goroutine a bit of time to finish its send. 1632 // 1633 // Less rare case: We also get here in the legitimate case of 1634 // Issue 7569, where the writer is still writing (or stalled), 1635 // but the server has already replied. In this case, we don't 1636 // want to wait too long, and we want to return false so this 1637 // connection isn't re-used. 1638 select { 1639 case err := <-pc.writeErrCh: 1640 return err == nil 1641 case <-time.After(50 * time.Millisecond): 1642 return false 1643 } 1644 } 1645 } 1646 1647 // responseAndError is how the goroutine reading from an HTTP/1 server 1648 // communicates with the goroutine doing the RoundTrip. 1649 type responseAndError struct { 1650 res *Response // else use this response (see res method) 1651 err error 1652 } 1653 1654 type requestAndChan struct { 1655 req *Request 1656 ch chan responseAndError // unbuffered; always send in select on callerGone 1657 1658 // whether the Transport (as opposed to the user client code) 1659 // added the Accept-Encoding gzip header. If the Transport 1660 // set it, only then do we transparently decode the gzip. 1661 addedGzip bool 1662 1663 // Optional blocking chan for Expect: 100-continue (for send). 1664 // If the request has an "Expect: 100-continue" header and 1665 // the server responds 100 Continue, readLoop send a value 1666 // to writeLoop via this chan. 1667 continueCh chan<- struct{} 1668 1669 callerGone <-chan struct{} // closed when roundTrip caller has returned 1670 } 1671 1672 // A writeRequest is sent by the readLoop's goroutine to the 1673 // writeLoop's goroutine to write a request while the read loop 1674 // concurrently waits on both the write response and the server's 1675 // reply. 1676 type writeRequest struct { 1677 req *transportRequest 1678 ch chan<- error 1679 1680 // Optional blocking chan for Expect: 100-continue (for receive). 1681 // If not nil, writeLoop blocks sending request body until 1682 // it receives from this chan. 1683 continueCh <-chan struct{} 1684 } 1685 1686 type httpError struct { 1687 err string 1688 timeout bool 1689 } 1690 1691 func (e *httpError) Error() string { return e.err } 1692 func (e *httpError) Timeout() bool { return e.timeout } 1693 func (e *httpError) Temporary() bool { return true } 1694 1695 var errTimeout error = &httpError{err: "net/http: timeout awaiting response headers", timeout: true} 1696 var errRequestCanceled = errors.New("net/http: request canceled") 1697 var errRequestCanceledConn = errors.New("net/http: request canceled while waiting for connection") // TODO: unify? 1698 1699 func nop() {} 1700 1701 // testHooks. Always non-nil. 1702 var ( 1703 testHookEnterRoundTrip = nop 1704 testHookWaitResLoop = nop 1705 testHookRoundTripRetried = nop 1706 testHookPrePendingDial = nop 1707 testHookPostPendingDial = nop 1708 1709 testHookMu sync.Locker = fakeLocker{} // guards following 1710 testHookReadLoopBeforeNextRead = nop 1711 ) 1712 1713 func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err error) { 1714 testHookEnterRoundTrip() 1715 if !pc.t.replaceReqCanceler(req.Request, pc.cancelRequest) { 1716 pc.t.putOrCloseIdleConn(pc) 1717 return nil, errRequestCanceled 1718 } 1719 pc.mu.Lock() 1720 pc.numExpectedResponses++ 1721 headerFn := pc.mutateHeaderFunc 1722 pc.mu.Unlock() 1723 1724 if headerFn != nil { 1725 headerFn(req.extraHeaders()) 1726 } 1727 1728 // Ask for a compressed version if the caller didn't set their 1729 // own value for Accept-Encoding. We only attempt to 1730 // uncompress the gzip stream if we were the layer that 1731 // requested it. 1732 requestedGzip := false 1733 if !pc.t.DisableCompression && 1734 req.Header.Get("Accept-Encoding") == "" && 1735 req.Header.Get("Range") == "" && 1736 req.Method != "HEAD" { 1737 // Request gzip only, not deflate. Deflate is ambiguous and 1738 // not as universally supported anyway. 1739 // See: http://www.gzip.org/zlib/zlib_faq.html#faq38 1740 // 1741 // Note that we don't request this for HEAD requests, 1742 // due to a bug in nginx: 1743 // http://trac.nginx.org/nginx/ticket/358 1744 // https://golang.org/issue/5522 1745 // 1746 // We don't request gzip if the request is for a range, since 1747 // auto-decoding a portion of a gzipped document will just fail 1748 // anyway. See https://golang.org/issue/8923 1749 requestedGzip = true 1750 req.extraHeaders().Set("Accept-Encoding", "gzip") 1751 } 1752 1753 var continueCh chan struct{} 1754 if req.ProtoAtLeast(1, 1) && req.Body != nil && req.expectsContinue() { 1755 continueCh = make(chan struct{}, 1) 1756 } 1757 1758 if pc.t.DisableKeepAlives { 1759 req.extraHeaders().Set("Connection", "close") 1760 } 1761 1762 gone := make(chan struct{}) 1763 defer close(gone) 1764 1765 // Write the request concurrently with waiting for a response, 1766 // in case the server decides to reply before reading our full 1767 // request body. 1768 startBytesWritten := pc.nwrite 1769 writeErrCh := make(chan error, 1) 1770 pc.writech <- writeRequest{req, writeErrCh, continueCh} 1771 1772 resc := make(chan responseAndError) 1773 pc.reqch <- requestAndChan{ 1774 req: req.Request, 1775 ch: resc, 1776 addedGzip: requestedGzip, 1777 continueCh: continueCh, 1778 callerGone: gone, 1779 } 1780 1781 var re responseAndError 1782 var respHeaderTimer <-chan time.Time 1783 cancelChan := req.Request.Cancel 1784 WaitResponse: 1785 for { 1786 testHookWaitResLoop() 1787 select { 1788 case err := <-writeErrCh: 1789 if err != nil { 1790 if pc.isCanceled() { 1791 err = errRequestCanceled 1792 } 1793 re = responseAndError{err: err} 1794 pc.close(fmt.Errorf("write error: %v", err)) 1795 break WaitResponse 1796 } 1797 if d := pc.t.ResponseHeaderTimeout; d > 0 { 1798 timer := time.NewTimer(d) 1799 defer timer.Stop() // prevent leaks 1800 respHeaderTimer = timer.C 1801 } 1802 case <-pc.closech: 1803 re = responseAndError{err: pc.mapRoundTripErrorAfterClosed(startBytesWritten)} 1804 break WaitResponse 1805 case <-respHeaderTimer: 1806 pc.close(errTimeout) 1807 re = responseAndError{err: errTimeout} 1808 break WaitResponse 1809 case re = <-resc: 1810 re.err = pc.mapRoundTripErrorFromReadLoop(startBytesWritten, re.err) 1811 break WaitResponse 1812 case <-cancelChan: 1813 pc.t.CancelRequest(req.Request) 1814 cancelChan = nil 1815 case <-req.Context().Done(): 1816 pc.t.CancelRequest(req.Request) 1817 cancelChan = nil 1818 } 1819 } 1820 1821 if re.err != nil { 1822 pc.t.setReqCanceler(req.Request, nil) 1823 } 1824 if (re.res == nil) == (re.err == nil) { 1825 panic("internal error: exactly one of res or err should be set") 1826 } 1827 return re.res, re.err 1828 } 1829 1830 // markReused marks this connection as having been successfully used for a 1831 // request and response. 1832 func (pc *persistConn) markReused() { 1833 pc.mu.Lock() 1834 pc.reused = true 1835 pc.mu.Unlock() 1836 } 1837 1838 // close closes the underlying TCP connection and closes 1839 // the pc.closech channel. 1840 // 1841 // The provided err is only for testing and debugging; in normal 1842 // circumstances it should never be seen by users. 1843 func (pc *persistConn) close(err error) { 1844 pc.mu.Lock() 1845 defer pc.mu.Unlock() 1846 pc.closeLocked(err) 1847 } 1848 1849 func (pc *persistConn) closeLocked(err error) { 1850 if err == nil { 1851 panic("nil error") 1852 } 1853 pc.broken = true 1854 if pc.closed == nil { 1855 pc.closed = err 1856 if pc.alt != nil { 1857 // Do nothing; can only get here via getConn's 1858 // handlePendingDial's putOrCloseIdleConn when 1859 // it turns out the abandoned connection in 1860 // flight ended up negotiating an alternate 1861 // protocol. We don't use the connection 1862 // freelist for http2. That's done by the 1863 // alternate protocol's RoundTripper. 1864 } else { 1865 pc.conn.Close() 1866 close(pc.closech) 1867 } 1868 } 1869 pc.mutateHeaderFunc = nil 1870 } 1871 1872 var portMap = map[string]string{ 1873 "http": "80", 1874 "https": "443", 1875 } 1876 1877 // canonicalAddr returns url.Host but always with a ":port" suffix 1878 func canonicalAddr(url *url.URL) string { 1879 addr := url.Host 1880 if !hasPort(addr) { 1881 return addr + ":" + portMap[url.Scheme] 1882 } 1883 return addr 1884 } 1885 1886 // bodyEOFSignal is used by the HTTP/1 transport when reading response 1887 // bodies to make sure we see the end of a response body before 1888 // proceeding and reading on the connection again. 1889 // 1890 // It wraps a ReadCloser but runs fn (if non-nil) at most 1891 // once, right before its final (error-producing) Read or Close call 1892 // returns. fn should return the new error to return from Read or Close. 1893 // 1894 // If earlyCloseFn is non-nil and Close is called before io.EOF is 1895 // seen, earlyCloseFn is called instead of fn, and its return value is 1896 // the return value from Close. 1897 type bodyEOFSignal struct { 1898 body io.ReadCloser 1899 mu sync.Mutex // guards following 4 fields 1900 closed bool // whether Close has been called 1901 rerr error // sticky Read error 1902 fn func(error) error // err will be nil on Read io.EOF 1903 earlyCloseFn func() error // optional alt Close func used if io.EOF not seen 1904 } 1905 1906 var errReadOnClosedResBody = errors.New("http: read on closed response body") 1907 1908 func (es *bodyEOFSignal) Read(p []byte) (n int, err error) { 1909 es.mu.Lock() 1910 closed, rerr := es.closed, es.rerr 1911 es.mu.Unlock() 1912 if closed { 1913 return 0, errReadOnClosedResBody 1914 } 1915 if rerr != nil { 1916 return 0, rerr 1917 } 1918 1919 n, err = es.body.Read(p) 1920 if err != nil { 1921 es.mu.Lock() 1922 defer es.mu.Unlock() 1923 if es.rerr == nil { 1924 es.rerr = err 1925 } 1926 err = es.condfn(err) 1927 } 1928 return 1929 } 1930 1931 func (es *bodyEOFSignal) Close() error { 1932 es.mu.Lock() 1933 defer es.mu.Unlock() 1934 if es.closed { 1935 return nil 1936 } 1937 es.closed = true 1938 if es.earlyCloseFn != nil && es.rerr != io.EOF { 1939 return es.earlyCloseFn() 1940 } 1941 err := es.body.Close() 1942 return es.condfn(err) 1943 } 1944 1945 // caller must hold es.mu. 1946 func (es *bodyEOFSignal) condfn(err error) error { 1947 if es.fn == nil { 1948 return err 1949 } 1950 err = es.fn(err) 1951 es.fn = nil 1952 return err 1953 } 1954 1955 // gzipReader wraps a response body so it can lazily 1956 // call gzip.NewReader on the first call to Read 1957 type gzipReader struct { 1958 body *bodyEOFSignal // underlying HTTP/1 response body framing 1959 zr *gzip.Reader // lazily-initialized gzip reader 1960 zerr error // any error from gzip.NewReader; sticky 1961 } 1962 1963 func (gz *gzipReader) Read(p []byte) (n int, err error) { 1964 if gz.zr == nil { 1965 if gz.zerr == nil { 1966 gz.zr, gz.zerr = gzip.NewReader(gz.body) 1967 } 1968 if gz.zerr != nil { 1969 return 0, gz.zerr 1970 } 1971 } 1972 1973 gz.body.mu.Lock() 1974 if gz.body.closed { 1975 err = errReadOnClosedResBody 1976 } 1977 gz.body.mu.Unlock() 1978 1979 if err != nil { 1980 return 0, err 1981 } 1982 return gz.zr.Read(p) 1983 } 1984 1985 func (gz *gzipReader) Close() error { 1986 return gz.body.Close() 1987 } 1988 1989 type readerAndCloser struct { 1990 io.Reader 1991 io.Closer 1992 } 1993 1994 type tlsHandshakeTimeoutError struct{} 1995 1996 func (tlsHandshakeTimeoutError) Timeout() bool { return true } 1997 func (tlsHandshakeTimeoutError) Temporary() bool { return true } 1998 func (tlsHandshakeTimeoutError) Error() string { return "net/http: TLS handshake timeout" } 1999 2000 // fakeLocker is a sync.Locker which does nothing. It's used to guard 2001 // test-only fields when not under test, to avoid runtime atomic 2002 // overhead. 2003 type fakeLocker struct{} 2004 2005 func (fakeLocker) Lock() {} 2006 func (fakeLocker) Unlock() {} 2007 2008 // cloneTLSConfig returns a shallow clone of the exported 2009 // fields of cfg, ignoring the unexported sync.Once, which 2010 // contains a mutex and must not be copied. 2011 // 2012 // The cfg must not be in active use by tls.Server, or else 2013 // there can still be a race with tls.Server updating SessionTicketKey 2014 // and our copying it, and also a race with the server setting 2015 // SessionTicketsDisabled=false on failure to set the random 2016 // ticket key. 2017 // 2018 // If cfg is nil, a new zero tls.Config is returned. 2019 func cloneTLSConfig(cfg *tls.Config) *tls.Config { 2020 if cfg == nil { 2021 return &tls.Config{} 2022 } 2023 return &tls.Config{ 2024 Rand: cfg.Rand, 2025 Time: cfg.Time, 2026 Certificates: cfg.Certificates, 2027 NameToCertificate: cfg.NameToCertificate, 2028 GetCertificate: cfg.GetCertificate, 2029 RootCAs: cfg.RootCAs, 2030 NextProtos: cfg.NextProtos, 2031 ServerName: cfg.ServerName, 2032 ClientAuth: cfg.ClientAuth, 2033 ClientCAs: cfg.ClientCAs, 2034 InsecureSkipVerify: cfg.InsecureSkipVerify, 2035 CipherSuites: cfg.CipherSuites, 2036 PreferServerCipherSuites: cfg.PreferServerCipherSuites, 2037 SessionTicketsDisabled: cfg.SessionTicketsDisabled, 2038 SessionTicketKey: cfg.SessionTicketKey, 2039 ClientSessionCache: cfg.ClientSessionCache, 2040 MinVersion: cfg.MinVersion, 2041 MaxVersion: cfg.MaxVersion, 2042 CurvePreferences: cfg.CurvePreferences, 2043 DynamicRecordSizingDisabled: cfg.DynamicRecordSizingDisabled, 2044 Renegotiation: cfg.Renegotiation, 2045 } 2046 } 2047 2048 // cloneTLSClientConfig is like cloneTLSConfig but omits 2049 // the fields SessionTicketsDisabled and SessionTicketKey. 2050 // This makes it safe to call cloneTLSClientConfig on a config 2051 // in active use by a server. 2052 func cloneTLSClientConfig(cfg *tls.Config) *tls.Config { 2053 if cfg == nil { 2054 return &tls.Config{} 2055 } 2056 return &tls.Config{ 2057 Rand: cfg.Rand, 2058 Time: cfg.Time, 2059 Certificates: cfg.Certificates, 2060 NameToCertificate: cfg.NameToCertificate, 2061 GetCertificate: cfg.GetCertificate, 2062 RootCAs: cfg.RootCAs, 2063 NextProtos: cfg.NextProtos, 2064 ServerName: cfg.ServerName, 2065 ClientAuth: cfg.ClientAuth, 2066 ClientCAs: cfg.ClientCAs, 2067 InsecureSkipVerify: cfg.InsecureSkipVerify, 2068 CipherSuites: cfg.CipherSuites, 2069 PreferServerCipherSuites: cfg.PreferServerCipherSuites, 2070 ClientSessionCache: cfg.ClientSessionCache, 2071 MinVersion: cfg.MinVersion, 2072 MaxVersion: cfg.MaxVersion, 2073 CurvePreferences: cfg.CurvePreferences, 2074 DynamicRecordSizingDisabled: cfg.DynamicRecordSizingDisabled, 2075 Renegotiation: cfg.Renegotiation, 2076 } 2077 } 2078 2079 type connLRU struct { 2080 ll *list.List // list.Element.Value type is of *persistConn 2081 m map[*persistConn]*list.Element 2082 } 2083 2084 // add adds pc to the head of the linked list. 2085 func (cl *connLRU) add(pc *persistConn) { 2086 if cl.ll == nil { 2087 cl.ll = list.New() 2088 cl.m = make(map[*persistConn]*list.Element) 2089 } 2090 ele := cl.ll.PushFront(pc) 2091 if _, ok := cl.m[pc]; ok { 2092 panic("persistConn was already in LRU") 2093 } 2094 cl.m[pc] = ele 2095 } 2096 2097 func (cl *connLRU) removeOldest() *persistConn { 2098 ele := cl.ll.Back() 2099 pc := ele.Value.(*persistConn) 2100 cl.ll.Remove(ele) 2101 delete(cl.m, pc) 2102 return pc 2103 } 2104 2105 // remove removes pc from cl. 2106 func (cl *connLRU) remove(pc *persistConn) { 2107 if ele, ok := cl.m[pc]; ok { 2108 cl.ll.Remove(ele) 2109 delete(cl.m, pc) 2110 } 2111 } 2112 2113 // len returns the number of items in the cache. 2114 func (cl *connLRU) len() int { 2115 return len(cl.m) 2116 }