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.
5 // HTTP client implementation. See RFC 7230 through 7235.
7 // This is the low-level Transport implementation of RoundTripper.
8 // The high-level interface is in client.go.
33 "golang_org/x/net/http/httpguts"
34 "golang_org/x/net/http/httpproxy"
37 // DefaultTransport is the default implementation of Transport and is
38 // used by DefaultClient. It establishes network connections as needed
39 // and caches them for reuse by subsequent calls. It uses HTTP proxies
40 // as directed by the $HTTP_PROXY and $NO_PROXY (or $http_proxy and
41 // $no_proxy) environment variables.
42 var DefaultTransport RoundTripper
= &Transport
{
43 Proxy
: ProxyFromEnvironment
,
44 DialContext
: (&net
.Dialer
{
45 Timeout
: 30 * time
.Second
,
46 KeepAlive
: 30 * time
.Second
,
50 IdleConnTimeout
: 90 * time
.Second
,
51 TLSHandshakeTimeout
: 10 * time
.Second
,
52 ExpectContinueTimeout
: 1 * time
.Second
,
55 // DefaultMaxIdleConnsPerHost is the default value of Transport's
56 // MaxIdleConnsPerHost.
57 const DefaultMaxIdleConnsPerHost
= 2
59 // connsPerHostClosedCh is a closed channel used by MaxConnsPerHost
60 // for the property that receives from a closed channel return the
62 var connsPerHostClosedCh
= make(chan struct{})
65 close(connsPerHostClosedCh
)
68 // Transport is an implementation of RoundTripper that supports HTTP,
69 // HTTPS, and HTTP proxies (for either HTTP or HTTPS with CONNECT).
71 // By default, Transport caches connections for future re-use.
72 // This may leave many open connections when accessing many hosts.
73 // This behavior can be managed using Transport's CloseIdleConnections method
74 // and the MaxIdleConnsPerHost and DisableKeepAlives fields.
76 // Transports should be reused instead of created as needed.
77 // Transports are safe for concurrent use by multiple goroutines.
79 // A Transport is a low-level primitive for making HTTP and HTTPS requests.
80 // For high-level functionality, such as cookies and redirects, see Client.
82 // Transport uses HTTP/1.1 for HTTP URLs and either HTTP/1.1 or HTTP/2
83 // for HTTPS URLs, depending on whether the server supports HTTP/2,
84 // and how the Transport is configured. The DefaultTransport supports HTTP/2.
85 // To explicitly enable HTTP/2 on a transport, use golang.org/x/net/http2
86 // and call ConfigureTransport. See the package docs for more about HTTP/2.
88 // The Transport will send CONNECT requests to a proxy for its own use
89 // when processing HTTPS requests, but Transport should generally not
90 // be used to send a CONNECT request. That is, the Request passed to
91 // the RoundTrip method should not have a Method of "CONNECT", as Go's
92 // HTTP/1.x implementation does not support full-duplex request bodies
93 // being written while the response body is streamed. Go's HTTP/2
94 // implementation does support full duplex, but many CONNECT proxies speak
97 // Responses with status codes in the 1xx range are either handled
98 // automatically (100 expect-continue) or ignored. The one
99 // exception is HTTP status code 101 (Switching Protocols), which is
100 // considered a terminal status and returned by RoundTrip. To see the
101 // ignored 1xx responses, use the httptrace trace package's
102 // ClientTrace.Got1xxResponse.
103 type Transport
struct {
105 wantIdle
bool // user has requested to close all idle conns
106 idleConn
map[connectMethodKey
][]*persistConn
// most recently used at end
107 idleConnCh
map[connectMethodKey
]chan *persistConn
111 reqCanceler
map[*Request
]func(error
)
113 altMu sync
.Mutex
// guards changing altProto only
114 altProto atomic
.Value
// of nil or map[string]RoundTripper, key is URI scheme
116 connCountMu sync
.Mutex
117 connPerHostCount
map[connectMethodKey
]int
118 connPerHostAvailable
map[connectMethodKey
]chan struct{}
120 // Proxy specifies a function to return a proxy for a given
121 // Request. If the function returns a non-nil error, the
122 // request is aborted with the provided error.
124 // The proxy type is determined by the URL scheme. "http",
125 // "https", and "socks5" are supported. If the scheme is empty,
126 // "http" is assumed.
128 // If Proxy is nil or returns a nil *URL, no proxy is used.
129 Proxy
func(*Request
) (*url
.URL
, error
)
131 // DialContext specifies the dial function for creating unencrypted TCP connections.
132 // If DialContext is nil (and the deprecated Dial below is also nil),
133 // then the transport dials using package net.
135 // DialContext runs concurrently with calls to RoundTrip.
136 // A RoundTrip call that initiates a dial may end up using
137 // an connection dialed previously when the earlier connection
138 // becomes idle before the later DialContext completes.
139 DialContext
func(ctx context
.Context
, network
, addr
string) (net
.Conn
, error
)
141 // Dial specifies the dial function for creating unencrypted TCP connections.
143 // Dial runs concurrently with calls to RoundTrip.
144 // A RoundTrip call that initiates a dial may end up using
145 // an connection dialed previously when the earlier connection
146 // becomes idle before the later Dial completes.
148 // Deprecated: Use DialContext instead, which allows the transport
149 // to cancel dials as soon as they are no longer needed.
150 // If both are set, DialContext takes priority.
151 Dial
func(network
, addr
string) (net
.Conn
, error
)
153 // DialTLS specifies an optional dial function for creating
154 // TLS connections for non-proxied HTTPS requests.
156 // If DialTLS is nil, Dial and TLSClientConfig are used.
158 // If DialTLS is set, the Dial hook is not used for HTTPS
159 // requests and the TLSClientConfig and TLSHandshakeTimeout
160 // are ignored. The returned net.Conn is assumed to already be
161 // past the TLS handshake.
162 DialTLS
func(network
, addr
string) (net
.Conn
, error
)
164 // TLSClientConfig specifies the TLS configuration to use with
166 // If nil, the default configuration is used.
167 // If non-nil, HTTP/2 support may not be enabled by default.
168 TLSClientConfig
*tls
.Config
170 // TLSHandshakeTimeout specifies the maximum amount of time waiting to
171 // wait for a TLS handshake. Zero means no timeout.
172 TLSHandshakeTimeout time
.Duration
174 // DisableKeepAlives, if true, disables HTTP keep-alives and
175 // will only use the connection to the server for a single
178 // This is unrelated to the similarly named TCP keep-alives.
179 DisableKeepAlives
bool
181 // DisableCompression, if true, prevents the Transport from
182 // requesting compression with an "Accept-Encoding: gzip"
183 // request header when the Request contains no existing
184 // Accept-Encoding value. If the Transport requests gzip on
185 // its own and gets a gzipped response, it's transparently
186 // decoded in the Response.Body. However, if the user
187 // explicitly requested gzip it is not automatically
189 DisableCompression
bool
191 // MaxIdleConns controls the maximum number of idle (keep-alive)
192 // connections across all hosts. Zero means no limit.
195 // MaxIdleConnsPerHost, if non-zero, controls the maximum idle
196 // (keep-alive) connections to keep per-host. If zero,
197 // DefaultMaxIdleConnsPerHost is used.
198 MaxIdleConnsPerHost
int
200 // MaxConnsPerHost optionally limits the total number of
201 // connections per host, including connections in the dialing,
202 // active, and idle states. On limit violation, dials will block.
204 // Zero means no limit.
206 // For HTTP/2, this currently only controls the number of new
207 // connections being created at a time, instead of the total
208 // number. In practice, hosts using HTTP/2 only have about one
209 // idle connection, though.
212 // IdleConnTimeout is the maximum amount of time an idle
213 // (keep-alive) connection will remain idle before closing
215 // Zero means no limit.
216 IdleConnTimeout time
.Duration
218 // ResponseHeaderTimeout, if non-zero, specifies the amount of
219 // time to wait for a server's response headers after fully
220 // writing the request (including its body, if any). This
221 // time does not include the time to read the response body.
222 ResponseHeaderTimeout time
.Duration
224 // ExpectContinueTimeout, if non-zero, specifies the amount of
225 // time to wait for a server's first response headers after fully
226 // writing the request headers if the request has an
227 // "Expect: 100-continue" header. Zero means no timeout and
228 // causes the body to be sent immediately, without
229 // waiting for the server to approve.
230 // This time does not include the time to send the request header.
231 ExpectContinueTimeout time
.Duration
233 // TLSNextProto specifies how the Transport switches to an
234 // alternate protocol (such as HTTP/2) after a TLS NPN/ALPN
235 // protocol negotiation. If Transport dials an TLS connection
236 // with a non-empty protocol name and TLSNextProto contains a
237 // map entry for that key (such as "h2"), then the func is
238 // called with the request's authority (such as "example.com"
239 // or "example.com:1234") and the TLS connection. The function
240 // must return a RoundTripper that then handles the request.
241 // If TLSNextProto is not nil, HTTP/2 support is not enabled
243 TLSNextProto
map[string]func(authority
string, c
*tls
.Conn
) RoundTripper
245 // ProxyConnectHeader optionally specifies headers to send to
246 // proxies during CONNECT requests.
247 ProxyConnectHeader Header
249 // MaxResponseHeaderBytes specifies a limit on how many
250 // response bytes are allowed in the server's response
253 // Zero means to use a default limit.
254 MaxResponseHeaderBytes
int64
256 // nextProtoOnce guards initialization of TLSNextProto and
257 // h2transport (via onceSetNextProtoDefaults)
258 nextProtoOnce sync
.Once
259 h2transport h2Transport
// non-nil if http2 wired up
262 // h2Transport is the interface we expect to be able to call from
263 // net/http against an *http2.Transport that's either bundled into
264 // h2_bundle.go or supplied by the user via x/net/http2.
266 // We name it with the "h2" prefix to stay out of the "http2" prefix
267 // namespace used by x/tools/cmd/bundle for h2_bundle.go.
268 type h2Transport
interface {
269 CloseIdleConnections()
272 // onceSetNextProtoDefaults initializes TLSNextProto.
273 // It must be called via t.nextProtoOnce.Do.
274 func (t
*Transport
) onceSetNextProtoDefaults() {
275 if strings
.Contains(os
.Getenv("GODEBUG"), "http2client=0") {
279 // If they've already configured http2 with
280 // golang.org/x/net/http2 instead of the bundled copy, try to
281 // get at its http2.Transport value (via the the "https"
282 // altproto map) so we can call CloseIdleConnections on it if
283 // requested. (Issue 22891)
284 altProto
, _
:= t
.altProto
.Load().(map[string]RoundTripper
)
285 if rv
:= reflect
.ValueOf(altProto
["https"]); rv
.IsValid() && rv
.Type().Kind() == reflect
.Struct
&& rv
.Type().NumField() == 1 {
286 if v
:= rv
.Field(0); v
.CanInterface() {
287 if h2i
, ok
:= v
.Interface().(h2Transport
); ok
{
293 if t
.TLSNextProto
!= nil {
294 // This is the documented way to disable http2 on a
298 if t
.TLSClientConfig
!= nil || t
.Dial
!= nil || t
.DialTLS
!= nil {
299 // Be conservative and don't automatically enable
300 // http2 if they've specified a custom TLS config or
301 // custom dialers. Let them opt-in themselves via
302 // http2.ConfigureTransport so we don't surprise them
303 // by modifying their tls.Config. Issue 14275.
306 t2
, err
:= http2configureTransport(t
)
308 log
.Printf("Error enabling Transport HTTP/2 support: %v", err
)
313 // Auto-configure the http2.Transport's MaxHeaderListSize from
314 // the http.Transport's MaxResponseHeaderBytes. They don't
315 // exactly mean the same thing, but they're close.
317 // TODO: also add this to x/net/http2.Configure Transport, behind
318 // a +build go1.7 build tag:
319 if limit1
:= t
.MaxResponseHeaderBytes
; limit1
!= 0 && t2
.MaxHeaderListSize
== 0 {
320 const h2max
= 1<<32 - 1
322 t2
.MaxHeaderListSize
= h2max
324 t2
.MaxHeaderListSize
= uint32(limit1
)
329 // ProxyFromEnvironment returns the URL of the proxy to use for a
330 // given request, as indicated by the environment variables
331 // HTTP_PROXY, HTTPS_PROXY and NO_PROXY (or the lowercase versions
332 // thereof). HTTPS_PROXY takes precedence over HTTP_PROXY for https
335 // The environment values may be either a complete URL or a
336 // "host[:port]", in which case the "http" scheme is assumed.
337 // An error is returned if the value is a different form.
339 // A nil URL and nil error are returned if no proxy is defined in the
340 // environment, or a proxy should not be used for the given request,
341 // as defined by NO_PROXY.
343 // As a special case, if req.URL.Host is "localhost" (with or without
344 // a port number), then a nil URL and nil error will be returned.
345 func ProxyFromEnvironment(req
*Request
) (*url
.URL
, error
) {
346 return envProxyFunc()(req
.URL
)
349 // ProxyURL returns a proxy function (for use in a Transport)
350 // that always returns the same URL.
351 func ProxyURL(fixedURL
*url
.URL
) func(*Request
) (*url
.URL
, error
) {
352 return func(*Request
) (*url
.URL
, error
) {
357 // transportRequest is a wrapper around a *Request that adds
358 // optional extra headers to write and stores any error to return
360 type transportRequest
struct {
361 *Request
// original request, not to be mutated
362 extra Header
// extra headers to write, or nil
363 trace
*httptrace
.ClientTrace
// optional
365 mu sync
.Mutex
// guards err
366 err error
// first setError value for mapRoundTripError to consider
369 func (tr
*transportRequest
) extraHeaders() Header
{
371 tr
.extra
= make(Header
)
376 func (tr
*transportRequest
) setError(err error
) {
384 // roundTrip implements a RoundTripper over HTTP.
385 func (t
*Transport
) roundTrip(req
*Request
) (*Response
, error
) {
386 t
.nextProtoOnce
.Do(t
.onceSetNextProtoDefaults
)
388 trace
:= httptrace
.ContextClientTrace(ctx
)
392 return nil, errors
.New("http: nil Request.URL")
394 if req
.Header
== nil {
396 return nil, errors
.New("http: nil Request.Header")
398 scheme
:= req
.URL
.Scheme
399 isHTTP
:= scheme
== "http" || scheme
== "https"
401 for k
, vv
:= range req
.Header
{
402 if !httpguts
.ValidHeaderFieldName(k
) {
403 return nil, fmt
.Errorf("net/http: invalid header field name %q", k
)
405 for _
, v
:= range vv
{
406 if !httpguts
.ValidHeaderFieldValue(v
) {
407 return nil, fmt
.Errorf("net/http: invalid header field value %q for key %v", v
, k
)
413 altProto
, _
:= t
.altProto
.Load().(map[string]RoundTripper
)
414 if altRT
:= altProto
[scheme
]; altRT
!= nil {
415 if resp
, err
:= altRT
.RoundTrip(req
); err
!= ErrSkipAltProtocol
{
421 return nil, &badStringError
{"unsupported protocol scheme", scheme
}
423 if req
.Method
!= "" && !validMethod(req
.Method
) {
424 return nil, fmt
.Errorf("net/http: invalid method %q", req
.Method
)
426 if req
.URL
.Host
== "" {
428 return nil, errors
.New("http: no Host in request URL")
435 return nil, ctx
.Err()
439 // treq gets modified by roundTrip, so we need to recreate for each retry.
440 treq
:= &transportRequest
{Request
: req
, trace
: trace
}
441 cm
, err
:= t
.connectMethodForRequest(treq
)
447 // Get the cached or newly-created connection to either the
448 // host (for http or https), the http proxy, or the http proxy
449 // pre-CONNECTed to https server. In any case, we'll be ready
450 // to send it requests.
451 pconn
, err
:= t
.getConn(treq
, cm
)
453 t
.setReqCanceler(req
, nil)
459 if pconn
.alt
!= nil {
461 t
.decHostConnCount(cm
.key()) // don't count cached http2 conns toward conns per host
462 t
.setReqCanceler(req
, nil) // not cancelable with CancelRequest
463 resp
, err
= pconn
.alt
.RoundTrip(req
)
465 resp
, err
= pconn
.roundTrip(treq
)
470 if !pconn
.shouldRetryRequest(req
, err
) {
471 // Issue 16465: return underlying net.Conn.Read error from peek,
472 // as we've historically done.
473 if e
, ok
:= err
.(transportReadFromServerError
); ok
{
478 testHookRoundTripRetried()
480 // Rewind the body if we're able to. (HTTP/2 does this itself so we only
481 // need to do it for HTTP/1.1 connections.)
482 if req
.GetBody
!= nil && pconn
.alt
== nil {
485 newReq
.Body
, err
= req
.GetBody()
494 // shouldRetryRequest reports whether we should retry sending a failed
495 // HTTP request on a new connection. The non-nil input error is the
496 // error from roundTrip.
497 func (pc
*persistConn
) shouldRetryRequest(req
*Request
, err error
) bool {
498 if http2isNoCachedConnError(err
) {
499 // Issue 16582: if the user started a bunch of
500 // requests at once, they can all pick the same conn
501 // and violate the server's max concurrent streams.
502 // Instead, match the HTTP/1 behavior for now and dial
503 // again to get a new TCP connection, rather than failing
507 if err
== errMissingHost
{
512 // This was a fresh connection. There's no reason the server
513 // should've hung up on us.
515 // Also, if we retried now, we could loop forever
516 // creating new connections and retrying if the server
517 // is just hanging up on us because it doesn't like
518 // our request (as opposed to sending an error).
521 if _
, ok
:= err
.(nothingWrittenError
); ok
{
522 // We never wrote anything, so it's safe to retry, if there's no body or we
523 // can "rewind" the body with GetBody.
524 return req
.outgoingLength() == 0 || req
.GetBody
!= nil
526 if !req
.isReplayable() {
527 // Don't retry non-idempotent requests.
530 if _
, ok
:= err
.(transportReadFromServerError
); ok
{
531 // We got some non-EOF net.Conn.Read failure reading
532 // the 1st response byte from the server.
535 if err
== errServerClosedIdle
{
536 // The server replied with io.EOF while we were trying to
537 // read the response. Probably an unfortunately keep-alive
538 // timeout, just as the client was writing a request.
541 return false // conservatively
544 // ErrSkipAltProtocol is a sentinel error value defined by Transport.RegisterProtocol.
545 var ErrSkipAltProtocol
= errors
.New("net/http: skip alternate protocol")
547 // RegisterProtocol registers a new protocol with scheme.
548 // The Transport will pass requests using the given scheme to rt.
549 // It is rt's responsibility to simulate HTTP request semantics.
551 // RegisterProtocol can be used by other packages to provide
552 // implementations of protocol schemes like "ftp" or "file".
554 // If rt.RoundTrip returns ErrSkipAltProtocol, the Transport will
555 // handle the RoundTrip itself for that one request, as if the
556 // protocol were not registered.
557 func (t
*Transport
) RegisterProtocol(scheme
string, rt RoundTripper
) {
559 defer t
.altMu
.Unlock()
560 oldMap
, _
:= t
.altProto
.Load().(map[string]RoundTripper
)
561 if _
, exists
:= oldMap
[scheme
]; exists
{
562 panic("protocol " + scheme
+ " already registered")
564 newMap
:= make(map[string]RoundTripper
)
565 for k
, v
:= range oldMap
{
569 t
.altProto
.Store(newMap
)
572 // CloseIdleConnections closes any connections which were previously
573 // connected from previous requests but are now sitting idle in
574 // a "keep-alive" state. It does not interrupt any connections currently
576 func (t
*Transport
) CloseIdleConnections() {
577 t
.nextProtoOnce
.Do(t
.onceSetNextProtoDefaults
)
583 t
.idleLRU
= connLRU
{}
585 for _
, conns
:= range m
{
586 for _
, pconn
:= range conns
{
587 pconn
.close(errCloseIdleConns
)
590 if t2
:= t
.h2transport
; t2
!= nil {
591 t2
.CloseIdleConnections()
595 // CancelRequest cancels an in-flight request by closing its connection.
596 // CancelRequest should only be called after RoundTrip has returned.
598 // Deprecated: Use Request.WithContext to create a request with a
599 // cancelable context instead. CancelRequest cannot cancel HTTP/2
601 func (t
*Transport
) CancelRequest(req
*Request
) {
602 t
.cancelRequest(req
, errRequestCanceled
)
605 // Cancel an in-flight request, recording the error value.
606 func (t
*Transport
) cancelRequest(req
*Request
, err error
) {
608 cancel
:= t
.reqCanceler
[req
]
609 delete(t
.reqCanceler
, req
)
617 // Private implementation past this point.
621 // proxyConfigOnce guards proxyConfig
622 envProxyOnce sync
.Once
623 envProxyFuncValue
func(*url
.URL
) (*url
.URL
, error
)
626 // defaultProxyConfig returns a ProxyConfig value looked up
627 // from the environment. This mitigates expensive lookups
628 // on some platforms (e.g. Windows).
629 func envProxyFunc() func(*url
.URL
) (*url
.URL
, error
) {
630 envProxyOnce
.Do(func() {
631 envProxyFuncValue
= httpproxy
.FromEnvironment().ProxyFunc()
633 return envProxyFuncValue
636 // resetProxyConfig is used by tests.
637 func resetProxyConfig() {
638 envProxyOnce
= sync
.Once
{}
639 envProxyFuncValue
= nil
642 func (t
*Transport
) connectMethodForRequest(treq
*transportRequest
) (cm connectMethod
, err error
) {
643 if port
:= treq
.URL
.Port(); !validPort(port
) {
644 return cm
, fmt
.Errorf("invalid URL port %q", port
)
646 cm
.targetScheme
= treq
.URL
.Scheme
647 cm
.targetAddr
= canonicalAddr(treq
.URL
)
649 cm
.proxyURL
, err
= t
.Proxy(treq
.Request
)
650 if err
== nil && cm
.proxyURL
!= nil {
651 if port
:= cm
.proxyURL
.Port(); !validPort(port
) {
652 return cm
, fmt
.Errorf("invalid proxy URL port %q", port
)
659 // proxyAuth returns the Proxy-Authorization header to set
660 // on requests, if applicable.
661 func (cm
*connectMethod
) proxyAuth() string {
662 if cm
.proxyURL
== nil {
665 if u
:= cm
.proxyURL
.User
; u
!= nil {
666 username
:= u
.Username()
667 password
, _
:= u
.Password()
668 return "Basic " + basicAuth(username
, password
)
673 // error values for debugging and testing, not seen by users.
675 errKeepAlivesDisabled
= errors
.New("http: putIdleConn: keep alives disabled")
676 errConnBroken
= errors
.New("http: putIdleConn: connection is in bad state")
677 errWantIdle
= errors
.New("http: putIdleConn: CloseIdleConnections was called")
678 errTooManyIdle
= errors
.New("http: putIdleConn: too many idle connections")
679 errTooManyIdleHost
= errors
.New("http: putIdleConn: too many idle connections for host")
680 errCloseIdleConns
= errors
.New("http: CloseIdleConnections called")
681 errReadLoopExiting
= errors
.New("http: persistConn.readLoop exiting")
682 errIdleConnTimeout
= errors
.New("http: idle connection timeout")
683 errNotCachingH2Conn
= errors
.New("http: not caching alternate protocol's connections")
685 // errServerClosedIdle is not seen by users for idempotent requests, but may be
686 // seen by a user if the server shuts down an idle connection and sends its FIN
687 // in flight with already-written POST body bytes from the client.
688 // See https://github.com/golang/go/issues/19943#issuecomment-355607646
689 errServerClosedIdle
= errors
.New("http: server closed idle connection")
692 // transportReadFromServerError is used by Transport.readLoop when the
693 // 1 byte peek read fails and we're actually anticipating a response.
694 // Usually this is just due to the inherent keep-alive shut down race,
695 // where the server closed the connection at the same time the client
696 // wrote. The underlying err field is usually io.EOF or some
697 // ECONNRESET sort of thing which varies by platform. But it might be
698 // the user's custom net.Conn.Read error too, so we carry it along for
699 // them to return from Transport.RoundTrip.
700 type transportReadFromServerError
struct {
704 func (e transportReadFromServerError
) Error() string {
705 return fmt
.Sprintf("net/http: Transport failed to read from server: %v", e
.err
)
708 func (t
*Transport
) putOrCloseIdleConn(pconn
*persistConn
) {
709 if err
:= t
.tryPutIdleConn(pconn
); err
!= nil {
714 func (t
*Transport
) maxIdleConnsPerHost() int {
715 if v
:= t
.MaxIdleConnsPerHost
; v
!= 0 {
718 return DefaultMaxIdleConnsPerHost
721 // tryPutIdleConn adds pconn to the list of idle persistent connections awaiting
723 // If pconn is no longer needed or not in a good state, tryPutIdleConn returns
724 // an error explaining why it wasn't registered.
725 // tryPutIdleConn does not close pconn. Use putOrCloseIdleConn instead for that.
726 func (t
*Transport
) tryPutIdleConn(pconn
*persistConn
) error
{
727 if t
.DisableKeepAlives || t
.MaxIdleConnsPerHost
< 0 {
728 return errKeepAlivesDisabled
730 if pconn
.isBroken() {
733 if pconn
.alt
!= nil {
734 return errNotCachingH2Conn
737 key
:= pconn
.cacheKey
740 defer t
.idleMu
.Unlock()
742 waitingDialer
:= t
.idleConnCh
[key
]
744 case waitingDialer
<- pconn
:
745 // We're done with this pconn and somebody else is
746 // currently waiting for a conn of this type (they're
747 // actively dialing, but this conn is ready
748 // first). Chrome calls this socket late binding. See
749 // https://insouciant.org/tech/connection-management-in-chromium/
752 if waitingDialer
!= nil {
753 // They had populated this, but their dial won
754 // first, so we can clean up this map entry.
755 delete(t
.idleConnCh
, key
)
761 if t
.idleConn
== nil {
762 t
.idleConn
= make(map[connectMethodKey
][]*persistConn
)
764 idles
:= t
.idleConn
[key
]
765 if len(idles
) >= t
.maxIdleConnsPerHost() {
766 return errTooManyIdleHost
768 for _
, exist
:= range idles
{
770 log
.Fatalf("dup idle pconn %p in freelist", pconn
)
773 t
.idleConn
[key
] = append(idles
, pconn
)
775 if t
.MaxIdleConns
!= 0 && t
.idleLRU
.len() > t
.MaxIdleConns
{
776 oldest
:= t
.idleLRU
.removeOldest()
777 oldest
.close(errTooManyIdle
)
778 t
.removeIdleConnLocked(oldest
)
780 if t
.IdleConnTimeout
> 0 {
781 if pconn
.idleTimer
!= nil {
782 pconn
.idleTimer
.Reset(t
.IdleConnTimeout
)
784 pconn
.idleTimer
= time
.AfterFunc(t
.IdleConnTimeout
, pconn
.closeConnIfStillIdle
)
787 pconn
.idleAt
= time
.Now()
791 // getIdleConnCh returns a channel to receive and return idle
792 // persistent connection for the given connectMethod.
793 // It may return nil, if persistent connections are not being used.
794 func (t
*Transport
) getIdleConnCh(cm connectMethod
) chan *persistConn
{
795 if t
.DisableKeepAlives
{
800 defer t
.idleMu
.Unlock()
802 if t
.idleConnCh
== nil {
803 t
.idleConnCh
= make(map[connectMethodKey
]chan *persistConn
)
805 ch
, ok
:= t
.idleConnCh
[key
]
807 ch
= make(chan *persistConn
)
808 t
.idleConnCh
[key
] = ch
813 func (t
*Transport
) getIdleConn(cm connectMethod
) (pconn
*persistConn
, idleSince time
.Time
) {
816 defer t
.idleMu
.Unlock()
818 pconns
, ok
:= t
.idleConn
[key
]
820 return nil, time
.Time
{}
822 if len(pconns
) == 1 {
824 delete(t
.idleConn
, key
)
826 // 2 or more cached connections; use the most
827 // recently used one at the end.
828 pconn
= pconns
[len(pconns
)-1]
829 t
.idleConn
[key
] = pconns
[:len(pconns
)-1]
831 t
.idleLRU
.remove(pconn
)
832 if pconn
.isBroken() {
833 // There is a tiny window where this is
834 // possible, between the connecting dying and
835 // the persistConn readLoop calling
836 // Transport.removeIdleConn. Just skip it and
840 return pconn
, pconn
.idleAt
844 // removeIdleConn marks pconn as dead.
845 func (t
*Transport
) removeIdleConn(pconn
*persistConn
) {
847 defer t
.idleMu
.Unlock()
848 t
.removeIdleConnLocked(pconn
)
851 // t.idleMu must be held.
852 func (t
*Transport
) removeIdleConnLocked(pconn
*persistConn
) {
853 if pconn
.idleTimer
!= nil {
854 pconn
.idleTimer
.Stop()
856 t
.idleLRU
.remove(pconn
)
857 key
:= pconn
.cacheKey
858 pconns
:= t
.idleConn
[key
]
863 if pconns
[0] == pconn
{
864 delete(t
.idleConn
, key
)
867 for i
, v
:= range pconns
{
871 // Slide down, keeping most recently-used
873 copy(pconns
[i
:], pconns
[i
+1:])
874 t
.idleConn
[key
] = pconns
[:len(pconns
)-1]
880 func (t
*Transport
) setReqCanceler(r
*Request
, fn
func(error
)) {
882 defer t
.reqMu
.Unlock()
883 if t
.reqCanceler
== nil {
884 t
.reqCanceler
= make(map[*Request
]func(error
))
887 t
.reqCanceler
[r
] = fn
889 delete(t
.reqCanceler
, r
)
893 // replaceReqCanceler replaces an existing cancel function. If there is no cancel function
894 // for the request, we don't set the function and return false.
895 // Since CancelRequest will clear the canceler, we can use the return value to detect if
896 // the request was canceled since the last setReqCancel call.
897 func (t
*Transport
) replaceReqCanceler(r
*Request
, fn
func(error
)) bool {
899 defer t
.reqMu
.Unlock()
900 _
, ok
:= t
.reqCanceler
[r
]
905 t
.reqCanceler
[r
] = fn
907 delete(t
.reqCanceler
, r
)
912 var zeroDialer net
.Dialer
914 func (t
*Transport
) dial(ctx context
.Context
, network
, addr
string) (net
.Conn
, error
) {
915 if t
.DialContext
!= nil {
916 return t
.DialContext(ctx
, network
, addr
)
919 c
, err
:= t
.Dial(network
, addr
)
920 if c
== nil && err
== nil {
921 err
= errors
.New("net/http: Transport.Dial hook returned (nil, nil)")
925 return zeroDialer
.DialContext(ctx
, network
, addr
)
928 // getConn dials and creates a new persistConn to the target as
929 // specified in the connectMethod. This includes doing a proxy CONNECT
930 // and/or setting up TLS. If this doesn't return an error, the persistConn
931 // is ready to write requests to.
932 func (t
*Transport
) getConn(treq
*transportRequest
, cm connectMethod
) (*persistConn
, error
) {
936 if trace
!= nil && trace
.GetConn
!= nil {
937 trace
.GetConn(cm
.addr())
939 if pc
, idleSince
:= t
.getIdleConn(cm
); pc
!= nil {
940 if trace
!= nil && trace
.GotConn
!= nil {
941 trace
.GotConn(pc
.gotIdleConnTrace(idleSince
))
943 // set request canceler to some non-nil function so we
944 // can detect whether it was cleared between now and when
945 // we enter roundTrip
946 t
.setReqCanceler(req
, func(error
) {})
950 type dialRes
struct {
954 dialc
:= make(chan dialRes
)
957 // Copy these hooks so we don't race on the postPendingDial in
958 // the goroutine we launch. Issue 11136.
959 testHookPrePendingDial
:= testHookPrePendingDial
960 testHookPostPendingDial
:= testHookPostPendingDial
962 handlePendingDial
:= func() {
963 testHookPrePendingDial()
965 if v
:= <-dialc
; v
.err
== nil {
966 t
.putOrCloseIdleConn(v
.pc
)
968 t
.decHostConnCount(cmKey
)
970 testHookPostPendingDial()
974 cancelc
:= make(chan error
, 1)
975 t
.setReqCanceler(req
, func(err error
) { cancelc
<- err
})
977 if t
.MaxConnsPerHost
> 0 {
979 case <-t
.incHostConnCount(cmKey
):
980 // count below conn per host limit; proceed
981 case pc
:= <-t
.getIdleConnCh(cm
):
982 if trace
!= nil && trace
.GotConn
!= nil {
983 trace
.GotConn(httptrace
.GotConnInfo
{Conn
: pc
.conn
, Reused
: pc
.isReused()})
987 return nil, errRequestCanceledConn
988 case <-req
.Context().Done():
989 return nil, req
.Context().Err()
990 case err
:= <-cancelc
:
991 if err
== errRequestCanceled
{
992 err
= errRequestCanceledConn
999 pc
, err
:= t
.dialConn(ctx
, cm
)
1000 dialc
<- dialRes
{pc
, err
}
1003 idleConnCh
:= t
.getIdleConnCh(cm
)
1006 // Our dial finished.
1008 if trace
!= nil && trace
.GotConn
!= nil && v
.pc
.alt
== nil {
1009 trace
.GotConn(httptrace
.GotConnInfo
{Conn
: v
.pc
.conn
})
1013 // Our dial failed. See why to return a nicer error
1015 t
.decHostConnCount(cmKey
)
1018 // It was an error due to cancelation, so prioritize that
1019 // error value. (Issue 16049)
1020 return nil, errRequestCanceledConn
1021 case <-req
.Context().Done():
1022 return nil, req
.Context().Err()
1023 case err
:= <-cancelc
:
1024 if err
== errRequestCanceled
{
1025 err
= errRequestCanceledConn
1029 // It wasn't an error due to cancelation, so
1030 // return the original error message:
1033 case pc
:= <-idleConnCh
:
1034 // Another request finished first and its net.Conn
1035 // became available before our dial. Or somebody
1036 // else's dial that they didn't use.
1037 // But our dial is still going, so give it away
1038 // when it finishes:
1040 if trace
!= nil && trace
.GotConn
!= nil {
1041 trace
.GotConn(httptrace
.GotConnInfo
{Conn
: pc
.conn
, Reused
: pc
.isReused()})
1046 return nil, errRequestCanceledConn
1047 case <-req
.Context().Done():
1049 return nil, req
.Context().Err()
1050 case err
:= <-cancelc
:
1052 if err
== errRequestCanceled
{
1053 err
= errRequestCanceledConn
1059 // incHostConnCount increments the count of connections for a
1060 // given host. It returns an already-closed channel if the count
1061 // is not at its limit; otherwise it returns a channel which is
1062 // notified when the count is below the limit.
1063 func (t
*Transport
) incHostConnCount(cmKey connectMethodKey
) <-chan struct{} {
1064 if t
.MaxConnsPerHost
<= 0 {
1065 return connsPerHostClosedCh
1067 t
.connCountMu
.Lock()
1068 defer t
.connCountMu
.Unlock()
1069 if t
.connPerHostCount
[cmKey
] == t
.MaxConnsPerHost
{
1070 if t
.connPerHostAvailable
== nil {
1071 t
.connPerHostAvailable
= make(map[connectMethodKey
]chan struct{})
1073 ch
, ok
:= t
.connPerHostAvailable
[cmKey
]
1075 ch
= make(chan struct{})
1076 t
.connPerHostAvailable
[cmKey
] = ch
1080 if t
.connPerHostCount
== nil {
1081 t
.connPerHostCount
= make(map[connectMethodKey
]int)
1083 t
.connPerHostCount
[cmKey
]++
1084 // return a closed channel to avoid race: if decHostConnCount is called
1085 // after incHostConnCount and during the nil check, decHostConnCount
1086 // will delete the channel since it's not being listened on yet.
1087 return connsPerHostClosedCh
1090 // decHostConnCount decrements the count of connections
1091 // for a given host.
1092 // See Transport.MaxConnsPerHost.
1093 func (t
*Transport
) decHostConnCount(cmKey connectMethodKey
) {
1094 if t
.MaxConnsPerHost
<= 0 {
1097 t
.connCountMu
.Lock()
1098 defer t
.connCountMu
.Unlock()
1099 t
.connPerHostCount
[cmKey
]--
1101 case t
.connPerHostAvailable
[cmKey
] <- struct{}{}:
1103 // close channel before deleting avoids getConn waiting forever in
1104 // case getConn has reference to channel but hasn't started waiting.
1105 // This could lead to more than MaxConnsPerHost in the unlikely case
1106 // that > 1 go routine has fetched the channel but none started waiting.
1107 if t
.connPerHostAvailable
[cmKey
] != nil {
1108 close(t
.connPerHostAvailable
[cmKey
])
1110 delete(t
.connPerHostAvailable
, cmKey
)
1112 if t
.connPerHostCount
[cmKey
] == 0 {
1113 delete(t
.connPerHostCount
, cmKey
)
1117 // connCloseListener wraps a connection, the transport that dialed it
1118 // and the connected-to host key so the host connection count can be
1119 // transparently decremented by whatever closes the embedded connection.
1120 type connCloseListener
struct {
1123 cmKey connectMethodKey
1127 func (c
*connCloseListener
) Close() error
{
1128 if atomic
.AddInt32(&c
.didClose
, 1) != 1 {
1131 err
:= c
.Conn
.Close()
1132 c
.t
.decHostConnCount(c
.cmKey
)
1136 // The connect method and the transport can both specify a TLS
1137 // Host name. The transport's name takes precedence if present.
1138 func chooseTLSHost(cm connectMethod
, t
*Transport
) string {
1140 if t
.TLSClientConfig
!= nil {
1141 tlsHost
= t
.TLSClientConfig
.ServerName
1144 tlsHost
= cm
.tlsHost()
1149 // Add TLS to a persistent connection, i.e. negotiate a TLS session. If pconn is already a TLS
1150 // tunnel, this function establishes a nested TLS session inside the encrypted channel.
1151 // The remote endpoint's name may be overridden by TLSClientConfig.ServerName.
1152 func (pconn
*persistConn
) addTLS(name
string, trace
*httptrace
.ClientTrace
) error
{
1153 // Initiate TLS and check remote host name against certificate.
1154 cfg
:= cloneTLSConfig(pconn
.t
.TLSClientConfig
)
1155 if cfg
.ServerName
== "" {
1156 cfg
.ServerName
= name
1158 plainConn
:= pconn
.conn
1159 tlsConn
:= tls
.Client(plainConn
, cfg
)
1160 errc
:= make(chan error
, 2)
1161 var timer
*time
.Timer
// for canceling TLS handshake
1162 if d
:= pconn
.t
.TLSHandshakeTimeout
; d
!= 0 {
1163 timer
= time
.AfterFunc(d
, func() {
1164 errc
<- tlsHandshakeTimeoutError
{}
1168 if trace
!= nil && trace
.TLSHandshakeStart
!= nil {
1169 trace
.TLSHandshakeStart()
1171 err
:= tlsConn
.Handshake()
1177 if err
:= <-errc
; err
!= nil {
1179 if trace
!= nil && trace
.TLSHandshakeDone
!= nil {
1180 trace
.TLSHandshakeDone(tls
.ConnectionState
{}, err
)
1184 cs
:= tlsConn
.ConnectionState()
1185 if trace
!= nil && trace
.TLSHandshakeDone
!= nil {
1186 trace
.TLSHandshakeDone(cs
, nil)
1188 pconn
.tlsState
= &cs
1189 pconn
.conn
= tlsConn
1193 func (t
*Transport
) dialConn(ctx context
.Context
, cm connectMethod
) (*persistConn
, error
) {
1194 pconn
:= &persistConn
{
1197 reqch
: make(chan requestAndChan
, 1),
1198 writech
: make(chan writeRequest
, 1),
1199 closech
: make(chan struct{}),
1200 writeErrCh
: make(chan error
, 1),
1201 writeLoopDone
: make(chan struct{}),
1203 trace
:= httptrace
.ContextClientTrace(ctx
)
1204 wrapErr
:= func(err error
) error
{
1205 if cm
.proxyURL
!= nil {
1206 // Return a typed error, per Issue 16997
1207 return &net
.OpError
{Op
: "proxyconnect", Net
: "tcp", Err
: err
}
1211 if cm
.scheme() == "https" && t
.DialTLS
!= nil {
1213 pconn
.conn
, err
= t
.DialTLS("tcp", cm
.addr())
1215 return nil, wrapErr(err
)
1217 if pconn
.conn
== nil {
1218 return nil, wrapErr(errors
.New("net/http: Transport.DialTLS returned (nil, nil)"))
1220 if tc
, ok
:= pconn
.conn
.(*tls
.Conn
); ok
{
1221 // Handshake here, in case DialTLS didn't. TLSNextProto below
1222 // depends on it for knowing the connection state.
1223 if trace
!= nil && trace
.TLSHandshakeStart
!= nil {
1224 trace
.TLSHandshakeStart()
1226 if err
:= tc
.Handshake(); err
!= nil {
1227 go pconn
.conn
.Close()
1228 if trace
!= nil && trace
.TLSHandshakeDone
!= nil {
1229 trace
.TLSHandshakeDone(tls
.ConnectionState
{}, err
)
1233 cs
:= tc
.ConnectionState()
1234 if trace
!= nil && trace
.TLSHandshakeDone
!= nil {
1235 trace
.TLSHandshakeDone(cs
, nil)
1237 pconn
.tlsState
= &cs
1240 conn
, err
:= t
.dial(ctx
, "tcp", cm
.addr())
1242 return nil, wrapErr(err
)
1245 if cm
.scheme() == "https" {
1246 var firstTLSHost
string
1247 if firstTLSHost
, _
, err
= net
.SplitHostPort(cm
.addr()); err
!= nil {
1248 return nil, wrapErr(err
)
1250 if err
= pconn
.addTLS(firstTLSHost
, trace
); err
!= nil {
1251 return nil, wrapErr(err
)
1258 case cm
.proxyURL
== nil:
1259 // Do nothing. Not using a proxy.
1260 case cm
.proxyURL
.Scheme
== "socks5":
1262 d
:= socksNewDialer("tcp", conn
.RemoteAddr().String())
1263 if u
:= cm
.proxyURL
.User
; u
!= nil {
1264 auth
:= &socksUsernamePassword
{
1265 Username
: u
.Username(),
1267 auth
.Password
, _
= u
.Password()
1268 d
.AuthMethods
= []socksAuthMethod
{
1269 socksAuthMethodNotRequired
,
1270 socksAuthMethodUsernamePassword
,
1272 d
.Authenticate
= auth
.Authenticate
1274 if _
, err
:= d
.DialWithConn(ctx
, conn
, "tcp", cm
.targetAddr
); err
!= nil {
1278 case cm
.targetScheme
== "http":
1279 pconn
.isProxy
= true
1280 if pa
:= cm
.proxyAuth(); pa
!= "" {
1281 pconn
.mutateHeaderFunc
= func(h Header
) {
1282 h
.Set("Proxy-Authorization", pa
)
1285 case cm
.targetScheme
== "https":
1287 hdr
:= t
.ProxyConnectHeader
1291 connectReq
:= &Request
{
1293 URL
: &url
.URL
{Opaque
: cm
.targetAddr
},
1294 Host
: cm
.targetAddr
,
1297 if pa
:= cm
.proxyAuth(); pa
!= "" {
1298 connectReq
.Header
.Set("Proxy-Authorization", pa
)
1300 connectReq
.Write(conn
)
1303 // Okay to use and discard buffered reader here, because
1304 // TLS server will not speak until spoken to.
1305 br
:= bufio
.NewReader(conn
)
1306 resp
, err
:= ReadResponse(br
, connectReq
)
1311 if resp
.StatusCode
!= 200 {
1312 f
:= strings
.SplitN(resp
.Status
, " ", 2)
1315 return nil, errors
.New("unknown status code")
1317 return nil, errors
.New(f
[1])
1321 if cm
.proxyURL
!= nil && cm
.targetScheme
== "https" {
1322 if err
:= pconn
.addTLS(cm
.tlsHost(), trace
); err
!= nil {
1327 if s
:= pconn
.tlsState
; s
!= nil && s
.NegotiatedProtocolIsMutual
&& s
.NegotiatedProtocol
!= "" {
1328 if next
, ok
:= t
.TLSNextProto
[s
.NegotiatedProtocol
]; ok
{
1329 return &persistConn
{alt
: next(cm
.targetAddr
, pconn
.conn
.(*tls
.Conn
))}, nil
1333 if t
.MaxConnsPerHost
> 0 {
1334 pconn
.conn
= &connCloseListener
{Conn
: pconn
.conn
, t
: t
, cmKey
: pconn
.cacheKey
}
1336 pconn
.br
= bufio
.NewReader(pconn
)
1337 pconn
.bw
= bufio
.NewWriter(persistConnWriter
{pconn
})
1339 go pconn
.writeLoop()
1343 // persistConnWriter is the io.Writer written to by pc.bw.
1344 // It accumulates the number of bytes written to the underlying conn,
1345 // so the retry logic can determine whether any bytes made it across
1347 // This is exactly 1 pointer field wide so it can go into an interface
1348 // without allocation.
1349 type persistConnWriter
struct {
1353 func (w persistConnWriter
) Write(p
[]byte) (n
int, err error
) {
1354 n
, err
= w
.pc
.conn
.Write(p
)
1355 w
.pc
.nwrite
+= int64(n
)
1359 // connectMethod is the map key (in its String form) for keeping persistent
1360 // TCP connections alive for subsequent HTTP requests.
1362 // A connect method may be of the following types:
1364 // Cache key form Description
1365 // ----------------- -------------------------
1366 // |http|foo.com http directly to server, no proxy
1367 // |https|foo.com https directly to server, no proxy
1368 // http://proxy.com|https|foo.com http to proxy, then CONNECT to foo.com
1369 // http://proxy.com|http http to proxy, http to anywhere after that
1370 // socks5://proxy.com|http|foo.com socks5 to proxy, then http to foo.com
1371 // socks5://proxy.com|https|foo.com socks5 to proxy, then https to foo.com
1372 // https://proxy.com|https|foo.com https to proxy, then CONNECT to foo.com
1373 // https://proxy.com|http https to proxy, http to anywhere after that
1375 type connectMethod
struct {
1376 proxyURL
*url
.URL
// nil for no proxy, else full proxy URL
1377 targetScheme
string // "http" or "https"
1378 // If proxyURL specifies an http or https proxy, and targetScheme is http (not https),
1379 // then targetAddr is not included in the connect method key, because the socket can
1380 // be reused for different targetAddr values.
1384 func (cm
*connectMethod
) key() connectMethodKey
{
1386 targetAddr
:= cm
.targetAddr
1387 if cm
.proxyURL
!= nil {
1388 proxyStr
= cm
.proxyURL
.String()
1389 if (cm
.proxyURL
.Scheme
== "http" || cm
.proxyURL
.Scheme
== "https") && cm
.targetScheme
== "http" {
1393 return connectMethodKey
{
1395 scheme
: cm
.targetScheme
,
1400 // scheme returns the first hop scheme: http, https, or socks5
1401 func (cm
*connectMethod
) scheme() string {
1402 if cm
.proxyURL
!= nil {
1403 return cm
.proxyURL
.Scheme
1405 return cm
.targetScheme
1408 // addr returns the first hop "host:port" to which we need to TCP connect.
1409 func (cm
*connectMethod
) addr() string {
1410 if cm
.proxyURL
!= nil {
1411 return canonicalAddr(cm
.proxyURL
)
1413 return cm
.targetAddr
1416 // tlsHost returns the host name to match against the peer's
1418 func (cm
*connectMethod
) tlsHost() string {
1421 h
= h
[:strings
.LastIndex(h
, ":")]
1426 // connectMethodKey is the map key version of connectMethod, with a
1427 // stringified proxy URL (or the empty string) instead of a pointer to
1429 type connectMethodKey
struct {
1430 proxy
, scheme
, addr
string
1433 func (k connectMethodKey
) String() string {
1434 // Only used by tests.
1435 return fmt
.Sprintf("%s|%s|%s", k
.proxy
, k
.scheme
, k
.addr
)
1438 // persistConn wraps a connection, usually a persistent one
1439 // (but may be used for non-keep-alive requests as well)
1440 type persistConn
struct {
1441 // alt optionally specifies the TLS NextProto RoundTripper.
1442 // This is used for HTTP/2 today and future protocols later.
1443 // If it's non-nil, the rest of the fields are unused.
1447 cacheKey connectMethodKey
1449 tlsState
*tls
.ConnectionState
1450 br
*bufio
.Reader
// from conn
1451 bw
*bufio
.Writer
// to conn
1452 nwrite
int64 // bytes written
1453 reqch
chan requestAndChan
// written by roundTrip; read by readLoop
1454 writech
chan writeRequest
// written by roundTrip; read by writeLoop
1455 closech
chan struct{} // closed when conn closed
1457 sawEOF
bool // whether we've seen EOF from conn; owned by readLoop
1458 readLimit
int64 // bytes allowed to be read; owned by readLoop
1459 // writeErrCh passes the request write error (usually nil)
1460 // from the writeLoop goroutine to the readLoop which passes
1461 // it off to the res.Body reader, which then uses it to decide
1462 // whether or not a connection can be reused. Issue 7569.
1463 writeErrCh
chan error
1465 writeLoopDone
chan struct{} // closed when write loop ends
1467 // Both guarded by Transport.idleMu:
1468 idleAt time
.Time
// time it last become idle
1469 idleTimer
*time
.Timer
// holding an AfterFunc to close it
1471 mu sync
.Mutex
// guards following fields
1472 numExpectedResponses
int
1473 closed error
// set non-nil when conn is closed, before closech is closed
1474 canceledErr error
// set non-nil if conn is canceled
1475 broken
bool // an error has happened on this connection; marked broken so it's not reused.
1476 reused
bool // whether conn has had successful request/response and is being reused.
1477 // mutateHeaderFunc is an optional func to modify extra
1478 // headers on each outbound request before it's written. (the
1479 // original Request given to RoundTrip is not modified)
1480 mutateHeaderFunc
func(Header
)
1483 func (pc
*persistConn
) maxHeaderResponseSize() int64 {
1484 if v
:= pc
.t
.MaxResponseHeaderBytes
; v
!= 0 {
1487 return 10 << 20 // conservative default; same as http2
1490 func (pc
*persistConn
) Read(p
[]byte) (n
int, err error
) {
1491 if pc
.readLimit
<= 0 {
1492 return 0, fmt
.Errorf("read limit of %d bytes exhausted", pc
.maxHeaderResponseSize())
1494 if int64(len(p
)) > pc
.readLimit
{
1495 p
= p
[:pc
.readLimit
]
1497 n
, err
= pc
.conn
.Read(p
)
1501 pc
.readLimit
-= int64(n
)
1505 // isBroken reports whether this connection is in a known broken state.
1506 func (pc
*persistConn
) isBroken() bool {
1508 b
:= pc
.closed != nil
1513 // canceled returns non-nil if the connection was closed due to
1514 // CancelRequest or due to context cancelation.
1515 func (pc
*persistConn
) canceled() error
{
1517 defer pc
.mu
.Unlock()
1518 return pc
.canceledErr
1521 // isReused reports whether this connection is in a known broken state.
1522 func (pc
*persistConn
) isReused() bool {
1529 func (pc
*persistConn
) gotIdleConnTrace(idleAt time
.Time
) (t httptrace
.GotConnInfo
) {
1531 defer pc
.mu
.Unlock()
1532 t
.Reused
= pc
.reused
1535 if !idleAt
.IsZero() {
1536 t
.IdleTime
= time
.Since(idleAt
)
1541 func (pc
*persistConn
) cancelRequest(err error
) {
1543 defer pc
.mu
.Unlock()
1544 pc
.canceledErr
= err
1545 pc
.closeLocked(errRequestCanceled
)
1548 // closeConnIfStillIdle closes the connection if it's still sitting idle.
1549 // This is what's called by the persistConn's idleTimer, and is run in its
1551 func (pc
*persistConn
) closeConnIfStillIdle() {
1554 defer t
.idleMu
.Unlock()
1555 if _
, ok
:= t
.idleLRU
.m
[pc
]; !ok
{
1559 t
.removeIdleConnLocked(pc
)
1560 pc
.close(errIdleConnTimeout
)
1563 // mapRoundTripError returns the appropriate error value for
1564 // persistConn.roundTrip.
1566 // The provided err is the first error that (*persistConn).roundTrip
1567 // happened to receive from its select statement.
1569 // The startBytesWritten value should be the value of pc.nwrite before the roundTrip
1570 // started writing the request.
1571 func (pc
*persistConn
) mapRoundTripError(req
*transportRequest
, startBytesWritten
int64, err error
) error
{
1576 // If the request was canceled, that's better than network
1577 // failures that were likely the result of tearing down the
1579 if cerr
:= pc
.canceled(); cerr
!= nil {
1583 // See if an error was set explicitly.
1591 if err
== errServerClosedIdle
{
1596 if _
, ok
:= err
.(transportReadFromServerError
); ok
{
1602 if pc
.nwrite
== startBytesWritten
{
1603 return nothingWrittenError
{err
}
1605 return fmt
.Errorf("net/http: HTTP/1.x transport connection broken: %v", err
)
1610 func (pc
*persistConn
) readLoop() {
1611 closeErr
:= errReadLoopExiting
// default value, if not changed below
1614 pc
.t
.removeIdleConn(pc
)
1617 tryPutIdleConn
:= func(trace
*httptrace
.ClientTrace
) bool {
1618 if err
:= pc
.t
.tryPutIdleConn(pc
); err
!= nil {
1620 if trace
!= nil && trace
.PutIdleConn
!= nil && err
!= errKeepAlivesDisabled
{
1621 trace
.PutIdleConn(err
)
1625 if trace
!= nil && trace
.PutIdleConn
!= nil {
1626 trace
.PutIdleConn(nil)
1631 // eofc is used to block caller goroutines reading from Response.Body
1632 // at EOF until this goroutines has (potentially) added the connection
1633 // back to the idle pool.
1634 eofc
:= make(chan struct{})
1635 defer close(eofc
) // unblock reader on errors
1637 // Read this once, before loop starts. (to avoid races in tests)
1639 testHookReadLoopBeforeNextRead
:= testHookReadLoopBeforeNextRead
1644 pc
.readLimit
= pc
.maxHeaderResponseSize()
1645 _
, err
:= pc
.br
.Peek(1)
1648 if pc
.numExpectedResponses
== 0 {
1649 pc
.readLoopPeekFailLocked(err
)
1656 trace
:= httptrace
.ContextClientTrace(rc
.req
.Context())
1660 resp
, err
= pc
.readResponse(rc
, trace
)
1662 err
= transportReadFromServerError
{err
}
1667 if pc
.readLimit
<= 0 {
1668 err
= fmt
.Errorf("net/http: server response headers exceeded %d bytes; aborted", pc
.maxHeaderResponseSize())
1672 case rc
.ch
<- responseAndError
{err
: err
}:
1673 case <-rc
.callerGone
:
1678 pc
.readLimit
= maxInt64
// effictively no limit for response bodies
1681 pc
.numExpectedResponses
--
1684 hasBody
:= rc
.req
.Method
!= "HEAD" && resp
.ContentLength
!= 0
1686 if resp
.Close || rc
.req
.Close || resp
.StatusCode
<= 199 {
1687 // Don't do keep-alive on error if either party requested a close
1688 // or we get an unexpected informational (1xx) response.
1689 // StatusCode 100 is already handled above.
1694 pc
.t
.setReqCanceler(rc
.req
, nil)
1696 // Put the idle conn back into the pool before we send the response
1697 // so if they process it quickly and make another request, they'll
1698 // get this same conn. But we use the unbuffered channel 'rc'
1699 // to guarantee that persistConn.roundTrip got out of its select
1700 // potentially waiting for this persistConn to close.
1704 pc
.wroteRequest() &&
1705 tryPutIdleConn(trace
)
1708 case rc
.ch
<- responseAndError
{res
: resp
}:
1709 case <-rc
.callerGone
:
1713 // Now that they've read from the unbuffered channel, they're safely
1714 // out of the select that also waits on this goroutine to die, so
1715 // we're allowed to exit now if needed (if alive is false)
1716 testHookReadLoopBeforeNextRead()
1720 waitForBodyRead
:= make(chan bool, 2)
1721 body
:= &bodyEOFSignal
{
1723 earlyCloseFn
: func() error
{
1724 waitForBodyRead
<- false
1725 <-eofc
// will be closed by deferred call at the end of the function
1729 fn
: func(err error
) error
{
1730 isEOF
:= err
== io
.EOF
1731 waitForBodyRead
<- isEOF
1733 <-eofc
// see comment above eofc declaration
1734 } else if err
!= nil {
1735 if cerr
:= pc
.canceled(); cerr
!= nil {
1744 if rc
.addedGzip
&& strings
.EqualFold(resp
.Header
.Get("Content-Encoding"), "gzip") {
1745 resp
.Body
= &gzipReader
{body
: body
}
1746 resp
.Header
.Del("Content-Encoding")
1747 resp
.Header
.Del("Content-Length")
1748 resp
.ContentLength
= -1
1749 resp
.Uncompressed
= true
1753 case rc
.ch
<- responseAndError
{res
: resp
}:
1754 case <-rc
.callerGone
:
1758 // Before looping back to the top of this function and peeking on
1759 // the bufio.Reader, wait for the caller goroutine to finish
1760 // reading the response body. (or for cancelation or death)
1762 case bodyEOF
:= <-waitForBodyRead
:
1763 pc
.t
.setReqCanceler(rc
.req
, nil) // before pc might return to idle pool
1767 pc
.wroteRequest() &&
1768 tryPutIdleConn(trace
)
1772 case <-rc
.req
.Cancel
:
1774 pc
.t
.CancelRequest(rc
.req
)
1775 case <-rc
.req
.Context().Done():
1777 pc
.t
.cancelRequest(rc
.req
, rc
.req
.Context().Err())
1782 testHookReadLoopBeforeNextRead()
1786 func (pc
*persistConn
) readLoopPeekFailLocked(peekErr error
) {
1787 if pc
.closed != nil {
1790 if n
:= pc
.br
.Buffered(); n
> 0 {
1791 buf
, _
:= pc
.br
.Peek(n
)
1792 log
.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v", buf
, peekErr
)
1794 if peekErr
== io
.EOF
{
1796 pc
.closeLocked(errServerClosedIdle
)
1798 pc
.closeLocked(fmt
.Errorf("readLoopPeekFailLocked: %v", peekErr
))
1802 // readResponse reads an HTTP response (or two, in the case of "Expect:
1803 // 100-continue") from the server. It returns the final non-100 one.
1804 // trace is optional.
1805 func (pc
*persistConn
) readResponse(rc requestAndChan
, trace
*httptrace
.ClientTrace
) (resp
*Response
, err error
) {
1806 if trace
!= nil && trace
.GotFirstResponseByte
!= nil {
1807 if peek
, err
:= pc
.br
.Peek(1); err
== nil && len(peek
) == 1 {
1808 trace
.GotFirstResponseByte()
1811 num1xx
:= 0 // number of informational 1xx headers received
1812 const max1xxResponses
= 5 // arbitrary bound on number of informational responses
1814 continueCh
:= rc
.continueCh
1816 resp
, err
= ReadResponse(pc
.br
, rc
.req
)
1820 resCode
:= resp
.StatusCode
1821 if continueCh
!= nil {
1823 if trace
!= nil && trace
.Got100Continue
!= nil {
1824 trace
.Got100Continue()
1826 continueCh
<- struct{}{}
1828 } else if resCode
>= 200 {
1833 is1xx
:= 100 <= resCode
&& resCode
<= 199
1834 // treat 101 as a terminal status, see issue 26161
1835 is1xxNonTerminal
:= is1xx
&& resCode
!= StatusSwitchingProtocols
1836 if is1xxNonTerminal
{
1838 if num1xx
> max1xxResponses
{
1839 return nil, errors
.New("net/http: too many 1xx informational responses")
1841 pc
.readLimit
= pc
.maxHeaderResponseSize() // reset the limit
1842 if trace
!= nil && trace
.Got1xxResponse
!= nil {
1843 if err
:= trace
.Got1xxResponse(resCode
, textproto
.MIMEHeader(resp
.Header
)); err
!= nil {
1851 resp
.TLS
= pc
.tlsState
1855 // waitForContinue returns the function to block until
1856 // any response, timeout or connection close. After any of them,
1857 // the function returns a bool which indicates if the body should be sent.
1858 func (pc
*persistConn
) waitForContinue(continueCh
<-chan struct{}) func() bool {
1859 if continueCh
== nil {
1862 return func() bool {
1863 timer
:= time
.NewTimer(pc
.t
.ExpectContinueTimeout
)
1867 case _
, ok
:= <-continueCh
:
1877 // nothingWrittenError wraps a write errors which ended up writing zero bytes.
1878 type nothingWrittenError
struct {
1882 func (pc
*persistConn
) writeLoop() {
1883 defer close(pc
.writeLoopDone
)
1886 case wr
:= <-pc
.writech
:
1887 startBytesWritten
:= pc
.nwrite
1888 err
:= wr
.req
.Request
.write(pc
.bw
, pc
.isProxy
, wr
.req
.extra
, pc
.waitForContinue(wr
.continueCh
))
1889 if bre
, ok
:= err
.(requestBodyReadError
); ok
{
1891 // Errors reading from the user's
1892 // Request.Body are high priority.
1893 // Set it here before sending on the
1894 // channels below or calling
1895 // pc.close() which tears town
1896 // connections and causes other
1898 wr
.req
.setError(err
)
1904 wr
.req
.Request
.closeBody()
1905 if pc
.nwrite
== startBytesWritten
{
1906 err
= nothingWrittenError
{err
}
1909 pc
.writeErrCh
<- err
// to the body reader, which might recycle us
1910 wr
.ch
<- err
// to the roundTrip function
1921 // maxWriteWaitBeforeConnReuse is how long the a Transport RoundTrip
1922 // will wait to see the Request's Body.Write result after getting a
1923 // response from the server. See comments in (*persistConn).wroteRequest.
1924 const maxWriteWaitBeforeConnReuse
= 50 * time
.Millisecond
1926 // wroteRequest is a check before recycling a connection that the previous write
1927 // (from writeLoop above) happened and was successful.
1928 func (pc
*persistConn
) wroteRequest() bool {
1930 case err
:= <-pc
.writeErrCh
:
1931 // Common case: the write happened well before the response, so
1932 // avoid creating a timer.
1935 // Rare case: the request was written in writeLoop above but
1936 // before it could send to pc.writeErrCh, the reader read it
1937 // all, processed it, and called us here. In this case, give the
1938 // write goroutine a bit of time to finish its send.
1940 // Less rare case: We also get here in the legitimate case of
1941 // Issue 7569, where the writer is still writing (or stalled),
1942 // but the server has already replied. In this case, we don't
1943 // want to wait too long, and we want to return false so this
1944 // connection isn't re-used.
1946 case err
:= <-pc
.writeErrCh
:
1948 case <-time
.After(maxWriteWaitBeforeConnReuse
):
1954 // responseAndError is how the goroutine reading from an HTTP/1 server
1955 // communicates with the goroutine doing the RoundTrip.
1956 type responseAndError
struct {
1957 res
*Response
// else use this response (see res method)
1961 type requestAndChan
struct {
1963 ch
chan responseAndError
// unbuffered; always send in select on callerGone
1965 // whether the Transport (as opposed to the user client code)
1966 // added the Accept-Encoding gzip header. If the Transport
1967 // set it, only then do we transparently decode the gzip.
1970 // Optional blocking chan for Expect: 100-continue (for send).
1971 // If the request has an "Expect: 100-continue" header and
1972 // the server responds 100 Continue, readLoop send a value
1973 // to writeLoop via this chan.
1974 continueCh
chan<- struct{}
1976 callerGone
<-chan struct{} // closed when roundTrip caller has returned
1979 // A writeRequest is sent by the readLoop's goroutine to the
1980 // writeLoop's goroutine to write a request while the read loop
1981 // concurrently waits on both the write response and the server's
1983 type writeRequest
struct {
1984 req
*transportRequest
1987 // Optional blocking chan for Expect: 100-continue (for receive).
1988 // If not nil, writeLoop blocks sending request body until
1989 // it receives from this chan.
1990 continueCh
<-chan struct{}
1993 type httpError
struct {
1998 func (e
*httpError
) Error() string { return e
.err
}
1999 func (e
*httpError
) Timeout() bool { return e
.timeout
}
2000 func (e
*httpError
) Temporary() bool { return true }
2002 var errTimeout error
= &httpError
{err
: "net/http: timeout awaiting response headers", timeout
: true}
2003 var errRequestCanceled
= errors
.New("net/http: request canceled")
2004 var errRequestCanceledConn
= errors
.New("net/http: request canceled while waiting for connection") // TODO: unify?
2008 // testHooks. Always non-nil.
2010 testHookEnterRoundTrip
= nop
2011 testHookWaitResLoop
= nop
2012 testHookRoundTripRetried
= nop
2013 testHookPrePendingDial
= nop
2014 testHookPostPendingDial
= nop
2016 testHookMu sync
.Locker
= fakeLocker
{} // guards following
2017 testHookReadLoopBeforeNextRead
= nop
2020 func (pc
*persistConn
) roundTrip(req
*transportRequest
) (resp
*Response
, err error
) {
2021 testHookEnterRoundTrip()
2022 if !pc
.t
.replaceReqCanceler(req
.Request
, pc
.cancelRequest
) {
2023 pc
.t
.putOrCloseIdleConn(pc
)
2024 return nil, errRequestCanceled
2027 pc
.numExpectedResponses
++
2028 headerFn
:= pc
.mutateHeaderFunc
2031 if headerFn
!= nil {
2032 headerFn(req
.extraHeaders())
2035 // Ask for a compressed version if the caller didn't set their
2036 // own value for Accept-Encoding. We only attempt to
2037 // uncompress the gzip stream if we were the layer that
2039 requestedGzip
:= false
2040 if !pc
.t
.DisableCompression
&&
2041 req
.Header
.Get("Accept-Encoding") == "" &&
2042 req
.Header
.Get("Range") == "" &&
2043 req
.Method
!= "HEAD" {
2044 // Request gzip only, not deflate. Deflate is ambiguous and
2045 // not as universally supported anyway.
2046 // See: http://www.gzip.org/zlib/zlib_faq.html#faq38
2048 // Note that we don't request this for HEAD requests,
2049 // due to a bug in nginx:
2050 // https://trac.nginx.org/nginx/ticket/358
2051 // https://golang.org/issue/5522
2053 // We don't request gzip if the request is for a range, since
2054 // auto-decoding a portion of a gzipped document will just fail
2055 // anyway. See https://golang.org/issue/8923
2056 requestedGzip
= true
2057 req
.extraHeaders().Set("Accept-Encoding", "gzip")
2060 var continueCh
chan struct{}
2061 if req
.ProtoAtLeast(1, 1) && req
.Body
!= nil && req
.expectsContinue() {
2062 continueCh
= make(chan struct{}, 1)
2065 if pc
.t
.DisableKeepAlives
{
2066 req
.extraHeaders().Set("Connection", "close")
2069 gone
:= make(chan struct{})
2074 pc
.t
.setReqCanceler(req
.Request
, nil)
2078 const debugRoundTrip
= false
2080 // Write the request concurrently with waiting for a response,
2081 // in case the server decides to reply before reading our full
2083 startBytesWritten
:= pc
.nwrite
2084 writeErrCh
:= make(chan error
, 1)
2085 pc
.writech
<- writeRequest
{req
, writeErrCh
, continueCh
}
2087 resc
:= make(chan responseAndError
)
2088 pc
.reqch
<- requestAndChan
{
2091 addedGzip
: requestedGzip
,
2092 continueCh
: continueCh
,
2096 var respHeaderTimer
<-chan time
.Time
2097 cancelChan
:= req
.Request
.Cancel
2098 ctxDoneChan
:= req
.Context().Done()
2100 testHookWaitResLoop()
2102 case err
:= <-writeErrCh
:
2104 req
.logf("writeErrCh resv: %T/%#v", err
, err
)
2107 pc
.close(fmt
.Errorf("write error: %v", err
))
2108 return nil, pc
.mapRoundTripError(req
, startBytesWritten
, err
)
2110 if d
:= pc
.t
.ResponseHeaderTimeout
; d
> 0 {
2112 req
.logf("starting timer for %v", d
)
2114 timer
:= time
.NewTimer(d
)
2115 defer timer
.Stop() // prevent leaks
2116 respHeaderTimer
= timer
.C
2120 req
.logf("closech recv: %T %#v", pc
.closed, pc
.closed)
2122 return nil, pc
.mapRoundTripError(req
, startBytesWritten
, pc
.closed)
2123 case <-respHeaderTimer
:
2125 req
.logf("timeout waiting for response headers.")
2127 pc
.close(errTimeout
)
2128 return nil, errTimeout
2130 if (re
.res
== nil) == (re
.err
== nil) {
2131 panic(fmt
.Sprintf("internal error: exactly one of res or err should be set; nil=%v", re
.res
== nil))
2134 req
.logf("resc recv: %p, %T/%#v", re
.res
, re
.err
, re
.err
)
2137 return nil, pc
.mapRoundTripError(req
, startBytesWritten
, re
.err
)
2141 pc
.t
.CancelRequest(req
.Request
)
2144 pc
.t
.cancelRequest(req
.Request
, req
.Context().Err())
2151 // tLogKey is a context WithValue key for test debugging contexts containing
2152 // a t.Logf func. See export_test.go's Request.WithT method.
2153 type tLogKey
struct{}
2155 func (tr
*transportRequest
) logf(format
string, args
...interface{}) {
2156 if logf
, ok
:= tr
.Request
.Context().Value(tLogKey
{}).(func(string, ...interface{})); ok
{
2157 logf(time
.Now().Format(time
.RFC3339Nano
)+": "+format
, args
...)
2161 // markReused marks this connection as having been successfully used for a
2162 // request and response.
2163 func (pc
*persistConn
) markReused() {
2169 // close closes the underlying TCP connection and closes
2170 // the pc.closech channel.
2172 // The provided err is only for testing and debugging; in normal
2173 // circumstances it should never be seen by users.
2174 func (pc
*persistConn
) close(err error
) {
2176 defer pc
.mu
.Unlock()
2180 func (pc
*persistConn
) closeLocked(err error
) {
2185 if pc
.closed == nil {
2188 // Do nothing; can only get here via getConn's
2189 // handlePendingDial's putOrCloseIdleConn when
2190 // it turns out the abandoned connection in
2191 // flight ended up negotiating an alternate
2192 // protocol. We don't use the connection
2193 // freelist for http2. That's done by the
2194 // alternate protocol's RoundTripper.
2200 pc
.mutateHeaderFunc
= nil
2203 var portMap
= map[string]string{
2209 // canonicalAddr returns url.Host but always with a ":port" suffix
2210 func canonicalAddr(url
*url
.URL
) string {
2211 addr
:= url
.Hostname()
2212 if v
, err
:= idnaASCII(addr
); err
== nil {
2217 port
= portMap
[url
.Scheme
]
2219 return net
.JoinHostPort(addr
, port
)
2222 // bodyEOFSignal is used by the HTTP/1 transport when reading response
2223 // bodies to make sure we see the end of a response body before
2224 // proceeding and reading on the connection again.
2226 // It wraps a ReadCloser but runs fn (if non-nil) at most
2227 // once, right before its final (error-producing) Read or Close call
2228 // returns. fn should return the new error to return from Read or Close.
2230 // If earlyCloseFn is non-nil and Close is called before io.EOF is
2231 // seen, earlyCloseFn is called instead of fn, and its return value is
2232 // the return value from Close.
2233 type bodyEOFSignal
struct {
2235 mu sync
.Mutex
// guards following 4 fields
2236 closed bool // whether Close has been called
2237 rerr error
// sticky Read error
2238 fn
func(error
) error
// err will be nil on Read io.EOF
2239 earlyCloseFn
func() error
// optional alt Close func used if io.EOF not seen
2242 var errReadOnClosedResBody
= errors
.New("http: read on closed response body")
2244 func (es
*bodyEOFSignal
) Read(p
[]byte) (n
int, err error
) {
2246 closed, rerr
:= es
.closed, es
.rerr
2249 return 0, errReadOnClosedResBody
2255 n
, err
= es
.body
.Read(p
)
2258 defer es
.mu
.Unlock()
2262 err
= es
.condfn(err
)
2267 func (es
*bodyEOFSignal
) Close() error
{
2269 defer es
.mu
.Unlock()
2274 if es
.earlyCloseFn
!= nil && es
.rerr
!= io
.EOF
{
2275 return es
.earlyCloseFn()
2277 err
:= es
.body
.Close()
2278 return es
.condfn(err
)
2281 // caller must hold es.mu.
2282 func (es
*bodyEOFSignal
) condfn(err error
) error
{
2291 // gzipReader wraps a response body so it can lazily
2292 // call gzip.NewReader on the first call to Read
2293 type gzipReader
struct {
2294 body
*bodyEOFSignal
// underlying HTTP/1 response body framing
2295 zr
*gzip
.Reader
// lazily-initialized gzip reader
2296 zerr error
// any error from gzip.NewReader; sticky
2299 func (gz
*gzipReader
) Read(p
[]byte) (n
int, err error
) {
2302 gz
.zr
, gz
.zerr
= gzip
.NewReader(gz
.body
)
2311 err
= errReadOnClosedResBody
2318 return gz
.zr
.Read(p
)
2321 func (gz
*gzipReader
) Close() error
{
2322 return gz
.body
.Close()
2325 type readerAndCloser
struct {
2330 type tlsHandshakeTimeoutError
struct{}
2332 func (tlsHandshakeTimeoutError
) Timeout() bool { return true }
2333 func (tlsHandshakeTimeoutError
) Temporary() bool { return true }
2334 func (tlsHandshakeTimeoutError
) Error() string { return "net/http: TLS handshake timeout" }
2336 // fakeLocker is a sync.Locker which does nothing. It's used to guard
2337 // test-only fields when not under test, to avoid runtime atomic
2339 type fakeLocker
struct{}
2341 func (fakeLocker
) Lock() {}
2342 func (fakeLocker
) Unlock() {}
2344 // clneTLSConfig returns a shallow clone of cfg, or a new zero tls.Config if
2345 // cfg is nil. This is safe to call even if cfg is in active use by a TLS
2346 // client or server.
2347 func cloneTLSConfig(cfg
*tls
.Config
) *tls
.Config
{
2349 return &tls
.Config
{}
2354 type connLRU
struct {
2355 ll
*list
.List
// list.Element.Value type is of *persistConn
2356 m
map[*persistConn
]*list
.Element
2359 // add adds pc to the head of the linked list.
2360 func (cl
*connLRU
) add(pc
*persistConn
) {
2363 cl
.m
= make(map[*persistConn
]*list
.Element
)
2365 ele
:= cl
.ll
.PushFront(pc
)
2366 if _
, ok
:= cl
.m
[pc
]; ok
{
2367 panic("persistConn was already in LRU")
2372 func (cl
*connLRU
) removeOldest() *persistConn
{
2374 pc
:= ele
.Value
.(*persistConn
)
2380 // remove removes pc from cl.
2381 func (cl
*connLRU
) remove(pc
*persistConn
) {
2382 if ele
, ok
:= cl
.m
[pc
]; ok
{
2388 // len returns the number of items in the cache.
2389 func (cl
*connLRU
) len() int {
2393 // validPort reports whether p (without the colon) is a valid port in
2394 // a URL, per RFC 3986 Section 3.2.3, which says the port may be
2395 // empty, or only contain digits.
2396 func validPort(p
string) bool {
2397 for _
, r
:= range []byte(p
) {
2398 if r
< '0' || r
> '9' {