Copyright 2011 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
HTTP client implementation. See RFC 7230 through 7235. This is the low-level Transport implementation of RoundTripper. The high-level interface is in client.go.

package http

import (
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	

	
	
)
DefaultTransport is the default implementation of Transport and is used by DefaultClient. It establishes network connections as needed and caches them for reuse by subsequent calls. It uses HTTP proxies as directed by the $HTTP_PROXY and $NO_PROXY (or $http_proxy and $no_proxy) environment variables.
DefaultMaxIdleConnsPerHost is the default value of Transport's MaxIdleConnsPerHost.
Transport is an implementation of RoundTripper that supports HTTP, HTTPS, and HTTP proxies (for either HTTP or HTTPS with CONNECT). By default, Transport caches connections for future re-use. This may leave many open connections when accessing many hosts. This behavior can be managed using Transport's CloseIdleConnections method and the MaxIdleConnsPerHost and DisableKeepAlives fields. Transports should be reused instead of created as needed. Transports are safe for concurrent use by multiple goroutines. A Transport is a low-level primitive for making HTTP and HTTPS requests. For high-level functionality, such as cookies and redirects, see Client. Transport uses HTTP/1.1 for HTTP URLs and either HTTP/1.1 or HTTP/2 for HTTPS URLs, depending on whether the server supports HTTP/2, and how the Transport is configured. The DefaultTransport supports HTTP/2. To explicitly enable HTTP/2 on a transport, use golang.org/x/net/http2 and call ConfigureTransport. See the package docs for more about HTTP/2. Responses with status codes in the 1xx range are either handled automatically (100 expect-continue) or ignored. The one exception is HTTP status code 101 (Switching Protocols), which is considered a terminal status and returned by RoundTrip. To see the ignored 1xx responses, use the httptrace trace package's ClientTrace.Got1xxResponse. Transport only retries a request upon encountering a network error if the request is idempotent and either has no body or has its Request.GetBody defined. HTTP requests are considered idempotent if they have HTTP methods GET, HEAD, OPTIONS, or TRACE; or if their Header map contains an "Idempotency-Key" or "X-Idempotency-Key" entry. If the idempotency key value is a zero-length slice, the request is treated as idempotent but the header is not sent on the wire.
type Transport struct {
	idleMu       sync.Mutex
	closeIdle    bool                                // user has requested to close all idle conns
	idleConn     map[connectMethodKey][]*persistConn // most recently used at end
	idleConnWait map[connectMethodKey]wantConnQueue  // waiting getConns
	idleLRU      connLRU

	reqMu       sync.Mutex
	reqCanceler map[cancelKey]func(error)

	altMu    sync.Mutex   // guards changing altProto only
	altProto atomic.Value // of nil or map[string]RoundTripper, key is URI scheme

	connsPerHostMu   sync.Mutex
	connsPerHost     map[connectMethodKey]int
	connsPerHostWait map[connectMethodKey]wantConnQueue // waiting getConns
Proxy specifies a function to return a proxy for a given Request. If the function returns a non-nil error, the request is aborted with the provided error. The proxy type is determined by the URL scheme. "http", "https", and "socks5" are supported. If the scheme is empty, "http" is assumed. If Proxy is nil or returns a nil *URL, no proxy is used.
	Proxy func(*Request) (*url.URL, error)
DialContext specifies the dial function for creating unencrypted TCP connections. If DialContext is nil (and the deprecated Dial below is also nil), then the transport dials using package net. DialContext runs concurrently with calls to RoundTrip. A RoundTrip call that initiates a dial may end up using a connection dialed previously when the earlier connection becomes idle before the later DialContext completes.
	DialContext func(ctx context.Context, network, addr string) (net.Conn, error)
Dial specifies the dial function for creating unencrypted TCP connections. Dial runs concurrently with calls to RoundTrip. A RoundTrip call that initiates a dial may end up using a connection dialed previously when the earlier connection becomes idle before the later Dial completes. Deprecated: Use DialContext instead, which allows the transport to cancel dials as soon as they are no longer needed. If both are set, DialContext takes priority.
	Dial func(network, addr string) (net.Conn, error)
DialTLSContext specifies an optional dial function for creating TLS connections for non-proxied HTTPS requests. If DialTLSContext is nil (and the deprecated DialTLS below is also nil), DialContext and TLSClientConfig are used. If DialTLSContext is set, the Dial and DialContext hooks are not used for HTTPS requests and the TLSClientConfig and TLSHandshakeTimeout are ignored. The returned net.Conn is assumed to already be past the TLS handshake.
	DialTLSContext func(ctx context.Context, network, addr string) (net.Conn, error)
DialTLS specifies an optional dial function for creating TLS connections for non-proxied HTTPS requests. Deprecated: Use DialTLSContext instead, which allows the transport to cancel dials as soon as they are no longer needed. If both are set, DialTLSContext takes priority.
	DialTLS func(network, addr string) (net.Conn, error)
TLSClientConfig specifies the TLS configuration to use with tls.Client. If nil, the default configuration is used. If non-nil, HTTP/2 support may not be enabled by default.
TLSHandshakeTimeout specifies the maximum amount of time waiting to wait for a TLS handshake. Zero means no timeout.
DisableKeepAlives, if true, disables HTTP keep-alives and will only use the connection to the server for a single HTTP request. This is unrelated to the similarly named TCP keep-alives.
DisableCompression, if true, prevents the Transport from requesting compression with an "Accept-Encoding: gzip" request header when the Request contains no existing Accept-Encoding value. If the Transport requests gzip on its own and gets a gzipped response, it's transparently decoded in the Response.Body. However, if the user explicitly requested gzip it is not automatically uncompressed.
MaxIdleConns controls the maximum number of idle (keep-alive) connections across all hosts. Zero means no limit.
MaxIdleConnsPerHost, if non-zero, controls the maximum idle (keep-alive) connections to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used.
MaxConnsPerHost optionally limits the total number of connections per host, including connections in the dialing, active, and idle states. On limit violation, dials will block. Zero means no limit.
IdleConnTimeout is the maximum amount of time an idle (keep-alive) connection will remain idle before closing itself. Zero means no limit.
ResponseHeaderTimeout, if non-zero, specifies the amount of time to wait for a server's response headers after fully writing the request (including its body, if any). This time does not include the time to read the response body.
ExpectContinueTimeout, if non-zero, specifies the amount of time to wait for a server's first response headers after fully writing the request headers if the request has an "Expect: 100-continue" header. Zero means no timeout and causes the body to be sent immediately, without waiting for the server to approve. This time does not include the time to send the request header.
TLSNextProto specifies how the Transport switches to an alternate protocol (such as HTTP/2) after a TLS ALPN protocol negotiation. If Transport dials an TLS connection with a non-empty protocol name and TLSNextProto contains a map entry for that key (such as "h2"), then the func is called with the request's authority (such as "example.com" or "example.com:1234") and the TLS connection. The function must return a RoundTripper that then handles the request. If TLSNextProto is not nil, HTTP/2 support is not enabled automatically.
	TLSNextProto map[string]func(authority string, c *tls.Conn) RoundTripper
ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. To set the header dynamically, see GetProxyConnectHeader.
GetProxyConnectHeader optionally specifies a func to return headers to send to proxyURL during a CONNECT request to the ip:port target. If it returns an error, the Transport's RoundTrip fails with that error. It can return (nil, nil) to not add headers. If GetProxyConnectHeader is non-nil, ProxyConnectHeader is ignored.
	GetProxyConnectHeader func(ctx context.Context, proxyURL *url.URL, target string) (Header, error)
MaxResponseHeaderBytes specifies a limit on how many response bytes are allowed in the server's response header. Zero means to use a default limit.
WriteBufferSize specifies the size of the write buffer used when writing to the transport. If zero, a default (currently 4KB) is used.
ReadBufferSize specifies the size of the read buffer used when reading from the transport. If zero, a default (currently 4KB) is used.
nextProtoOnce guards initialization of TLSNextProto and h2transport (via onceSetNextProtoDefaults)
	nextProtoOnce      sync.Once
	h2transport        h2Transport // non-nil if http2 wired up
	tlsNextProtoWasNil bool        // whether TLSNextProto was nil when the Once fired
ForceAttemptHTTP2 controls whether HTTP/2 is enabled when a non-zero Dial, DialTLS, or DialContext func or TLSClientConfig is provided. By default, use of any those fields conservatively disables HTTP/2. To use a custom dialer or TLS config and still attempt HTTP/2 upgrades, set this to true.
A cancelKey is the key of the reqCanceler map. We wrap the *Request in this type since we want to use the original request, not any transient one created by roundTrip.
type cancelKey struct {
	req *Request
}

func ( *Transport) () int {
	if .WriteBufferSize > 0 {
		return .WriteBufferSize
	}
	return 4 << 10
}

func ( *Transport) () int {
	if .ReadBufferSize > 0 {
		return .ReadBufferSize
	}
	return 4 << 10
}
h2Transport is the interface we expect to be able to call from net/http against an *http2.Transport that's either bundled into h2_bundle.go or supplied by the user via x/net/http2. We name it with the "h2" prefix to stay out of the "http2" prefix namespace used by x/tools/cmd/bundle for h2_bundle.go.
type h2Transport interface {
	CloseIdleConnections()
}

func ( *Transport) () bool {
	return .DialTLS != nil || .DialTLSContext != nil
}
onceSetNextProtoDefaults initializes TLSNextProto. It must be called via t.nextProtoOnce.Do.
func ( *Transport) () {
	.tlsNextProtoWasNil = (.TLSNextProto == nil)
	if strings.Contains(os.Getenv("GODEBUG"), "http2client=0") {
		return
	}
If they've already configured http2 with golang.org/x/net/http2 instead of the bundled copy, try to get at its http2.Transport value (via the "https" altproto map) so we can call CloseIdleConnections on it if requested. (Issue 22891)
	,  := .altProto.Load().(map[string]RoundTripper)
	if  := reflect.ValueOf(["https"]); .IsValid() && .Type().Kind() == reflect.Struct && .Type().NumField() == 1 {
		if  := .Field(0); .CanInterface() {
			if ,  := .Interface().(h2Transport);  {
				.h2transport = 
				return
			}
		}
	}

This is the documented way to disable http2 on a Transport.
		return
	}
Be conservative and don't automatically enable http2 if they've specified a custom TLS config or custom dialers. Let them opt-in themselves via http2.ConfigureTransport so we don't surprise them by modifying their tls.Config. Issue 14275. However, if ForceAttemptHTTP2 is true, it overrides the above checks.
		return
	}
	if omitBundledHTTP2 {
		return
	}
	,  := http2configureTransports()
	if  != nil {
		log.Printf("Error enabling Transport HTTP/2 support: %v", )
		return
	}
	.h2transport = 
Auto-configure the http2.Transport's MaxHeaderListSize from the http.Transport's MaxResponseHeaderBytes. They don't exactly mean the same thing, but they're close. TODO: also add this to x/net/http2.Configure Transport, behind a +build go1.7 build tag:
	if  := .MaxResponseHeaderBytes;  != 0 && .MaxHeaderListSize == 0 {
		const  = 1<<32 - 1
		if  >=  {
			.MaxHeaderListSize = 
		} else {
			.MaxHeaderListSize = uint32()
		}
	}
}
ProxyFromEnvironment returns the URL of the proxy to use for a given request, as indicated by the environment variables HTTP_PROXY, HTTPS_PROXY and NO_PROXY (or the lowercase versions thereof). HTTPS_PROXY takes precedence over HTTP_PROXY for https requests. The environment values may be either a complete URL or a "host[:port]", in which case the "http" scheme is assumed. An error is returned if the value is a different form. A nil URL and nil error are returned if no proxy is defined in the environment, or a proxy should not be used for the given request, as defined by NO_PROXY. As a special case, if req.URL.Host is "localhost" (with or without a port number), then a nil URL and nil error will be returned.
func ( *Request) (*url.URL, error) {
	return envProxyFunc()(.URL)
}
ProxyURL returns a proxy function (for use in a Transport) that always returns the same URL.
func ( *url.URL) func(*Request) (*url.URL, error) {
	return func(*Request) (*url.URL, error) {
		return , nil
	}
}
transportRequest is a wrapper around a *Request that adds optional extra headers to write and stores any error to return from roundTrip.
type transportRequest struct {
	*Request                         // original request, not to be mutated
	extra     Header                 // extra headers to write, or nil
	trace     *httptrace.ClientTrace // optional
	cancelKey cancelKey

	mu  sync.Mutex // guards err
	err error      // first setError value for mapRoundTripError to consider
}

func ( *transportRequest) () Header {
	if .extra == nil {
		.extra = make(Header)
	}
	return .extra
}

func ( *transportRequest) ( error) {
	.mu.Lock()
	if .err == nil {
		.err = 
	}
	.mu.Unlock()
}
useRegisteredProtocol reports whether an alternate protocol (as registered with Transport.RegisterProtocol) should be respected for this request.
If this request requires HTTP/1, don't use the "https" alternate protocol, which is used by the HTTP/2 code to take over requests if there's an existing cached HTTP/2 connection.
		return false
	}
	return true
}
alternateRoundTripper returns the alternate RoundTripper to use for this request if the Request's URL scheme requires one, or nil for the normal case of using the Transport.
func ( *Transport) ( *Request) RoundTripper {
	if !.useRegisteredProtocol() {
		return nil
	}
	,  := .altProto.Load().(map[string]RoundTripper)
	return [.URL.Scheme]
}
roundTrip implements a RoundTripper over HTTP.
func ( *Transport) ( *Request) (*Response, error) {
	.nextProtoOnce.Do(.onceSetNextProtoDefaults)
	 := .Context()
	 := httptrace.ContextClientTrace()

	if .URL == nil {
		.closeBody()
		return nil, errors.New("http: nil Request.URL")
	}
	if .Header == nil {
		.closeBody()
		return nil, errors.New("http: nil Request.Header")
	}
	 := .URL.Scheme
	 :=  == "http" ||  == "https"
	if  {
		for ,  := range .Header {
			if !httpguts.ValidHeaderFieldName() {
				.closeBody()
				return nil, fmt.Errorf("net/http: invalid header field name %q", )
			}
			for ,  := range  {
				if !httpguts.ValidHeaderFieldValue() {
					.closeBody()
					return nil, fmt.Errorf("net/http: invalid header field value %q for key %v", , )
				}
			}
		}
	}

	 := 
	 := cancelKey{}
	 = setupRewindBody()

	if  := .alternateRoundTripper();  != nil {
		if ,  := .RoundTrip();  != ErrSkipAltProtocol {
			return , 
		}
		var  error
		,  = rewindBody()
		if  != nil {
			return nil, 
		}
	}
	if ! {
		.closeBody()
		return nil, badStringError("unsupported protocol scheme", )
	}
	if .Method != "" && !validMethod(.Method) {
		.closeBody()
		return nil, fmt.Errorf("net/http: invalid method %q", .Method)
	}
	if .URL.Host == "" {
		.closeBody()
		return nil, errors.New("http: no Host in request URL")
	}

	for {
		select {
		case <-.Done():
			.closeBody()
			return nil, .Err()
		default:
		}
treq gets modified by roundTrip, so we need to recreate for each retry.
		 := &transportRequest{Request: , trace: , cancelKey: }
		,  := .connectMethodForRequest()
		if  != nil {
			.closeBody()
			return nil, 
		}
Get the cached or newly-created connection to either the host (for http or https), the http proxy, or the http proxy pre-CONNECTed to https server. In any case, we'll be ready to send it requests.
		,  := .getConn(, )
		if  != nil {
			.setReqCanceler(, nil)
			.closeBody()
			return nil, 
		}

		var  *Response
HTTP/2 path.
			.setReqCanceler(, nil) // not cancelable with CancelRequest
			,  = .alt.RoundTrip()
		} else {
			,  = .roundTrip()
		}
		if  == nil {
			.Request = 
			return , nil
		}
Failed. Clean up and determine whether to retry.
Issue 16465: return underlying net.Conn.Read error from peek, as we've historically done.
			if ,  := .(transportReadFromServerError);  {
				 = .err
			}
			return nil, 
		}
		testHookRoundTripRetried()
Rewind the body if we're able to.
		,  = rewindBody()
		if  != nil {
			return nil, 
		}
	}
}

var errCannotRewind = errors.New("net/http: cannot rewind body after connection loss")

type readTrackingBody struct {
	io.ReadCloser
	didRead  bool
	didClose bool
}

func ( *readTrackingBody) ( []byte) (int, error) {
	.didRead = true
	return .ReadCloser.Read()
}

func ( *readTrackingBody) () error {
	.didClose = true
	return .ReadCloser.Close()
}
setupRewindBody returns a new request with a custom body wrapper that can report whether the body needs rewinding. This lets rewindBody avoid an error result when the request does not have GetBody but the body hasn't been read at all yet.
func ( *Request) *Request {
	if .Body == nil || .Body == NoBody {
		return 
	}
	 := *
	.Body = &readTrackingBody{ReadCloser: .Body}
	return &
}
rewindBody returns a new request with the body rewound. It returns req unmodified if the body does not need rewinding. rewindBody takes care of closing req.Body when appropriate (in all cases except when rewindBody returns req unmodified).
func ( *Request) ( *Request,  error) {
	if .Body == nil || .Body == NoBody || (!.Body.(*readTrackingBody).didRead && !.Body.(*readTrackingBody).didClose) {
		return , nil // nothing to rewind
	}
	if !.Body.(*readTrackingBody).didClose {
		.closeBody()
	}
	if .GetBody == nil {
		return nil, errCannotRewind
	}
	,  := .GetBody()
	if  != nil {
		return nil, 
	}
	 := *
	.Body = &readTrackingBody{ReadCloser: }
	return &, nil
}
shouldRetryRequest reports whether we should retry sending a failed HTTP request on a new connection. The non-nil input error is the error from roundTrip.
Issue 16582: if the user started a bunch of requests at once, they can all pick the same conn and violate the server's max concurrent streams. Instead, match the HTTP/1 behavior for now and dial again to get a new TCP connection, rather than failing this request.
		return true
	}
User error.
		return false
	}
This was a fresh connection. There's no reason the server should've hung up on us. Also, if we retried now, we could loop forever creating new connections and retrying if the server is just hanging up on us because it doesn't like our request (as opposed to sending an error).
		return false
	}
We never wrote anything, so it's safe to retry, if there's no body or we can "rewind" the body with GetBody.
		return .outgoingLength() == 0 || .GetBody != nil
	}
Don't retry non-idempotent requests.
		return false
	}
We got some non-EOF net.Conn.Read failure reading the 1st response byte from the server.
		return true
	}
The server replied with io.EOF while we were trying to read the response. Probably an unfortunately keep-alive timeout, just as the client was writing a request.
		return true
	}
	return false // conservatively
}
ErrSkipAltProtocol is a sentinel error value defined by Transport.RegisterProtocol.
var ErrSkipAltProtocol = errors.New("net/http: skip alternate protocol")
RegisterProtocol registers a new protocol with scheme. The Transport will pass requests using the given scheme to rt. It is rt's responsibility to simulate HTTP request semantics. RegisterProtocol can be used by other packages to provide implementations of protocol schemes like "ftp" or "file". If rt.RoundTrip returns ErrSkipAltProtocol, the Transport will handle the RoundTrip itself for that one request, as if the protocol were not registered.
func ( *Transport) ( string,  RoundTripper) {
	.altMu.Lock()
	defer .altMu.Unlock()
	,  := .altProto.Load().(map[string]RoundTripper)
	if ,  := [];  {
		panic("protocol " +  + " already registered")
	}
	 := make(map[string]RoundTripper)
	for ,  := range  {
		[] = 
	}
	[] = 
	.altProto.Store()
}
CloseIdleConnections closes any connections which were previously connected from previous requests but are now sitting idle in a "keep-alive" state. It does not interrupt any connections currently in use.
func ( *Transport) () {
	.nextProtoOnce.Do(.onceSetNextProtoDefaults)
	.idleMu.Lock()
	 := .idleConn
	.idleConn = nil
	.closeIdle = true // close newly idle connections
	.idleLRU = connLRU{}
	.idleMu.Unlock()
	for ,  := range  {
		for ,  := range  {
			.close(errCloseIdleConns)
		}
	}
	if  := .h2transport;  != nil {
		.CloseIdleConnections()
	}
}
CancelRequest cancels an in-flight request by closing its connection. CancelRequest should only be called after RoundTrip has returned. Deprecated: Use Request.WithContext to create a request with a cancelable context instead. CancelRequest cannot cancel HTTP/2 requests.
Cancel an in-flight request, recording the error value. Returns whether the request was canceled.
func ( *Transport) ( cancelKey,  error) bool {
	.reqMu.Lock()
	 := .reqCanceler[]
	delete(.reqCanceler, )
	.reqMu.Unlock()
	if  != nil {
		()
	}

	return  != nil
}
Private implementation past this point.

proxyConfigOnce guards proxyConfig
defaultProxyConfig returns a ProxyConfig value looked up from the environment. This mitigates expensive lookups on some platforms (e.g. Windows).
resetProxyConfig is used by tests.
func () {
	envProxyOnce = sync.Once{}
	envProxyFuncValue = nil
}

func ( *Transport) ( *transportRequest) ( connectMethod,  error) {
	.targetScheme = .URL.Scheme
	.targetAddr = canonicalAddr(.URL)
	if .Proxy != nil {
		.proxyURL,  = .Proxy(.Request)
	}
	.onlyH1 = .requiresHTTP1()
	return , 
}
proxyAuth returns the Proxy-Authorization header to set on requests, if applicable.
func ( *connectMethod) () string {
	if .proxyURL == nil {
		return ""
	}
	if  := .proxyURL.User;  != nil {
		 := .Username()
		,  := .Password()
		return "Basic " + basicAuth(, )
	}
	return ""
}
error values for debugging and testing, not seen by users.
var (
	errKeepAlivesDisabled = errors.New("http: putIdleConn: keep alives disabled")
	errConnBroken         = errors.New("http: putIdleConn: connection is in bad state")
	errCloseIdle          = errors.New("http: putIdleConn: CloseIdleConnections was called")
	errTooManyIdle        = errors.New("http: putIdleConn: too many idle connections")
	errTooManyIdleHost    = errors.New("http: putIdleConn: too many idle connections for host")
	errCloseIdleConns     = errors.New("http: CloseIdleConnections called")
	errReadLoopExiting    = errors.New("http: persistConn.readLoop exiting")
	errIdleConnTimeout    = errors.New("http: idle connection timeout")
errServerClosedIdle is not seen by users for idempotent requests, but may be seen by a user if the server shuts down an idle connection and sends its FIN in flight with already-written POST body bytes from the client. See https://github.com/golang/go/issues/19943#issuecomment-355607646
	errServerClosedIdle = errors.New("http: server closed idle connection")
)
transportReadFromServerError is used by Transport.readLoop when the 1 byte peek read fails and we're actually anticipating a response. Usually this is just due to the inherent keep-alive shut down race, where the server closed the connection at the same time the client wrote. The underlying err field is usually io.EOF or some ECONNRESET sort of thing which varies by platform. But it might be the user's custom net.Conn.Read error too, so we carry it along for them to return from Transport.RoundTrip.
type transportReadFromServerError struct {
	err error
}

func ( transportReadFromServerError) () error { return .err }

func ( transportReadFromServerError) () string {
	return fmt.Sprintf("net/http: Transport failed to read from server: %v", .err)
}

func ( *Transport) ( *persistConn) {
	if  := .tryPutIdleConn();  != nil {
		.close()
	}
}

func ( *Transport) () int {
	if  := .MaxIdleConnsPerHost;  != 0 {
		return 
	}
	return DefaultMaxIdleConnsPerHost
}
tryPutIdleConn adds pconn to the list of idle persistent connections awaiting a new request. If pconn is no longer needed or not in a good state, tryPutIdleConn returns an error explaining why it wasn't registered. tryPutIdleConn does not close pconn. Use putOrCloseIdleConn instead for that.
func ( *Transport) ( *persistConn) error {
	if .DisableKeepAlives || .MaxIdleConnsPerHost < 0 {
		return errKeepAlivesDisabled
	}
	if .isBroken() {
		return errConnBroken
	}
	.markReused()

	.idleMu.Lock()
	defer .idleMu.Unlock()
HTTP/2 (pconn.alt != nil) connections do not come out of the idle list, because multiple goroutines can use them simultaneously. If this is an HTTP/2 connection being “returned,” we're done.
	if .alt != nil && .idleLRU.m[] != nil {
		return nil
	}
Deliver pconn to goroutine waiting for idle connection, if any. (They may be actively dialing, but this conn is ready first. Chrome calls this socket late binding. See https://www.chromium.org/developers/design-documents/network-stack#TOC-Connection-Management.)
	 := .cacheKey
	if ,  := .idleConnWait[];  {
		 := false
HTTP/1. Loop over the waiting list until we find a w that isn't done already, and hand it pconn.
			for .len() > 0 {
				 := .popFront()
				if .tryDeliver(, nil) {
					 = true
					break
				}
			}
HTTP/2. Can hand the same pconn to everyone in the waiting list, and we still won't be done: we want to put it in the idle list unconditionally, for any future clients too.
			for .len() > 0 {
				 := .popFront()
				.tryDeliver(, nil)
			}
		}
		if .len() == 0 {
			delete(.idleConnWait, )
		} else {
			.idleConnWait[] = 
		}
		if  {
			return nil
		}
	}

	if .closeIdle {
		return errCloseIdle
	}
	if .idleConn == nil {
		.idleConn = make(map[connectMethodKey][]*persistConn)
	}
	 := .idleConn[]
	if len() >= .maxIdleConnsPerHost() {
		return errTooManyIdleHost
	}
	for ,  := range  {
		if  ==  {
			log.Fatalf("dup idle pconn %p in freelist", )
		}
	}
	.idleConn[] = append(, )
	.idleLRU.add()
	if .MaxIdleConns != 0 && .idleLRU.len() > .MaxIdleConns {
		 := .idleLRU.removeOldest()
		.close(errTooManyIdle)
		.removeIdleConnLocked()
	}
Set idle timer, but only for HTTP/1 (pconn.alt == nil). The HTTP/2 implementation manages the idle timer itself (see idleConnTimeout in h2_bundle.go).
	if .IdleConnTimeout > 0 && .alt == nil {
		if .idleTimer != nil {
			.idleTimer.Reset(.IdleConnTimeout)
		} else {
			.idleTimer = time.AfterFunc(.IdleConnTimeout, .closeConnIfStillIdle)
		}
	}
	.idleAt = time.Now()
	return nil
}
queueForIdleConn queues w to receive the next idle connection for w.cm. As an optimization hint to the caller, queueForIdleConn reports whether it successfully delivered an already-idle connection.
func ( *Transport) ( *wantConn) ( bool) {
	if .DisableKeepAlives {
		return false
	}

	.idleMu.Lock()
	defer .idleMu.Unlock()
Stop closing connections that become idle - we might want one. (That is, undo the effect of t.CloseIdleConnections.)
Happens in test hook.
		return false
	}
If IdleConnTimeout is set, calculate the oldest persistConn.idleAt time we're willing to use a cached idle conn.
	var  time.Time
	if .IdleConnTimeout > 0 {
		 = time.Now().Add(-.IdleConnTimeout)
	}
Look for most recently-used idle connection.
	if ,  := .idleConn[.key];  {
		 := false
		 := false
		for len() > 0 && ! {
			 := [len()-1]
See whether this connection has been idle too long, considering only the wall time (the Round(0)), in case this is a laptop or VM coming out of suspend with previously cached idle connections.
			 := !.IsZero() && .idleAt.Round(0).Before()
Async cleanup. Launch in its own goroutine (as if a time.AfterFunc called it); it acquires idleMu, which we're holding, and does a synchronous net.Conn.Close.
				go .closeConnIfStillIdle()
			}
If either persistConn.readLoop has marked the connection broken, but Transport.removeIdleConn has not yet removed it from the idle list, or if this persistConn is too old (it was idle too long), then ignore it and look for another. In both cases it's already in the process of being closed.
				 = [:len()-1]
				continue
			}
			 = .tryDeliver(, nil)
			if  {
HTTP/2: multiple clients can share pconn. Leave it in the list.
HTTP/1: only one client can use pconn. Remove it from the list.
					.idleLRU.remove()
					 = [:len()-1]
				}
			}
			 = true
		}
		if len() > 0 {
			.idleConn[.key] = 
		} else {
			delete(.idleConn, .key)
		}
		if  {
			return 
		}
	}
Register to receive next connection that becomes idle.
removeIdleConn marks pconn as dead.
func ( *Transport) ( *persistConn) bool {
	.idleMu.Lock()
	defer .idleMu.Unlock()
	return .removeIdleConnLocked()
}
t.idleMu must be held.
func ( *Transport) ( *persistConn) bool {
	if .idleTimer != nil {
		.idleTimer.Stop()
	}
	.idleLRU.remove()
	 := .cacheKey
	 := .idleConn[]
	var  bool
	switch len() {
Nothing
	case 1:
		if [0] ==  {
			delete(.idleConn, )
			 = true
		}
	default:
		for ,  := range  {
			if  !=  {
				continue
Slide down, keeping most recently-used conns at the end.
			copy([:], [+1:])
			.idleConn[] = [:len()-1]
			 = true
			break
		}
	}
	return 
}

func ( *Transport) ( cancelKey,  func(error)) {
	.reqMu.Lock()
	defer .reqMu.Unlock()
	if .reqCanceler == nil {
		.reqCanceler = make(map[cancelKey]func(error))
	}
	if  != nil {
		.reqCanceler[] = 
	} else {
		delete(.reqCanceler, )
	}
}
replaceReqCanceler replaces an existing cancel function. If there is no cancel function for the request, we don't set the function and return false. Since CancelRequest will clear the canceler, we can use the return value to detect if the request was canceled since the last setReqCancel call.
func ( *Transport) ( cancelKey,  func(error)) bool {
	.reqMu.Lock()
	defer .reqMu.Unlock()
	,  := .reqCanceler[]
	if ! {
		return false
	}
	if  != nil {
		.reqCanceler[] = 
	} else {
		delete(.reqCanceler, )
	}
	return true
}

var zeroDialer net.Dialer

func ( *Transport) ( context.Context, ,  string) (net.Conn, error) {
	if .DialContext != nil {
		return .DialContext(, , )
	}
	if .Dial != nil {
		,  := .Dial(, )
		if  == nil &&  == nil {
			 = errors.New("net/http: Transport.Dial hook returned (nil, nil)")
		}
		return , 
	}
	return zeroDialer.DialContext(, , )
}
A wantConn records state about a wanted connection (that is, an active call to getConn). The conn may be gotten by dialing or by finding an idle connection, or a cancellation may make the conn no longer wanted. These three options are racing against each other and use wantConn to coordinate and agree about the winning outcome.
type wantConn struct {
	cm    connectMethod
	key   connectMethodKey // cm.key()
	ctx   context.Context  // context for dial
	ready chan struct{}    // closed when pc, err pair is delivered
hooks for testing to know when dials are done beforeDial is called in the getConn goroutine when the dial is queued. afterDial is called when the dial is completed or cancelled.
	beforeDial func()
	afterDial  func()

	mu  sync.Mutex // protects pc, err, close(ready)
	pc  *persistConn
	err error
}
waiting reports whether w is still waiting for an answer (connection or error).
func ( *wantConn) () bool {
	select {
	case <-.ready:
		return false
	default:
		return true
	}
}
tryDeliver attempts to deliver pc, err to w and reports whether it succeeded.
func ( *wantConn) ( *persistConn,  error) bool {
	.mu.Lock()
	defer .mu.Unlock()

	if .pc != nil || .err != nil {
		return false
	}

	.pc = 
	.err = 
	if .pc == nil && .err == nil {
		panic("net/http: internal error: misuse of tryDeliver")
	}
	close(.ready)
	return true
}
cancel marks w as no longer wanting a result (for example, due to cancellation). If a connection has been delivered already, cancel returns it with t.putOrCloseIdleConn.
func ( *wantConn) ( *Transport,  error) {
	.mu.Lock()
	if .pc == nil && .err == nil {
		close(.ready) // catch misbehavior in future delivery
	}
	 := .pc
	.pc = nil
	.err = 
	.mu.Unlock()

	if  != nil {
		.putOrCloseIdleConn()
	}
}
A wantConnQueue is a queue of wantConns.
This is a queue, not a deque. It is split into two stages - head[headPos:] and tail. popFront is trivial (headPos++) on the first stage, and pushBack is trivial (append) on the second stage. If the first stage is empty, popFront can swap the first and second stages to remedy the situation. This two-stage split is analogous to the use of two lists in Okasaki's purely functional queue but without the overhead of reversing the list when swapping stages.
len returns the number of items in the queue.
func ( *wantConnQueue) () int {
	return len(.head) - .headPos + len(.tail)
}
pushBack adds w to the back of the queue.
func ( *wantConnQueue) ( *wantConn) {
	.tail = append(.tail, )
}
popFront removes and returns the wantConn at the front of the queue.
func ( *wantConnQueue) () *wantConn {
	if .headPos >= len(.head) {
		if len(.tail) == 0 {
			return nil
Pick up tail as new head, clear tail.
		.head, .headPos, .tail = .tail, 0, .head[:0]
	}
	 := .head[.headPos]
	.head[.headPos] = nil
	.headPos++
	return 
}
peekFront returns the wantConn at the front of the queue without removing it.
func ( *wantConnQueue) () *wantConn {
	if .headPos < len(.head) {
		return .head[.headPos]
	}
	if len(.tail) > 0 {
		return .tail[0]
	}
	return nil
}
cleanFront pops any wantConns that are no longer waiting from the head of the queue, reporting whether any were popped.
func ( *wantConnQueue) () ( bool) {
	for {
		 := .peekFront()
		if  == nil || .waiting() {
			return 
		}
		.popFront()
		 = true
	}
}

func ( *Transport) ( context.Context, ,  string) ( net.Conn,  error) {
	if .DialTLSContext != nil {
		,  = .DialTLSContext(, , )
	} else {
		,  = .DialTLS(, )
	}
	if  == nil &&  == nil {
		 = errors.New("net/http: Transport.DialTLS or DialTLSContext returned (nil, nil)")
	}
	return
}
getConn dials and creates a new persistConn to the target as specified in the connectMethod. This includes doing a proxy CONNECT and/or setting up TLS. If this doesn't return an error, the persistConn is ready to write requests to.
func ( *Transport) ( *transportRequest,  connectMethod) ( *persistConn,  error) {
	 := .Request
	 := .trace
	 := .Context()
	if  != nil && .GetConn != nil {
		.GetConn(.addr())
	}

	 := &wantConn{
		cm:         ,
		key:        .key(),
		ctx:        ,
		ready:      make(chan struct{}, 1),
		beforeDial: testHookPrePendingDial,
		afterDial:  testHookPostPendingDial,
	}
	defer func() {
		if  != nil {
			.cancel(, )
		}
	}()
Queue for idle connection.
	if  := .queueForIdleConn();  {
Trace only for HTTP/1. HTTP/2 calls trace.GotConn itself.
		if .alt == nil &&  != nil && .GotConn != nil {
			.GotConn(.gotIdleConnTrace(.idleAt))
set request canceler to some non-nil function so we can detect whether it was cleared between now and when we enter roundTrip
		.setReqCanceler(.cancelKey, func(error) {})
		return , nil
	}

	 := make(chan error, 1)
	.setReqCanceler(.cancelKey, func( error) {  <-  })
Queue for permission to dial.
Wait for completion or cancellation.
	select {
Trace success but only for HTTP/1. HTTP/2 calls trace.GotConn itself.
		if .pc != nil && .pc.alt == nil &&  != nil && .GotConn != nil {
			.GotConn(httptrace.GotConnInfo{Conn: .pc.conn, Reused: .pc.isReused()})
		}
If the request has been cancelled, that's probably what caused w.err; if so, prefer to return the cancellation error (see golang.org/issue/16049).
			select {
			case <-.Cancel:
				return nil, errRequestCanceledConn
			case <-.Context().Done():
				return nil, .Context().Err()
			case  := <-:
				if  == errRequestCanceled {
					 = errRequestCanceledConn
				}
				return nil, 
return below
			}
		}
		return .pc, .err
	case <-.Cancel:
		return nil, errRequestCanceledConn
	case <-.Context().Done():
		return nil, .Context().Err()
	case  := <-:
		if  == errRequestCanceled {
			 = errRequestCanceledConn
		}
		return nil, 
	}
}
queueForDial queues w to wait for permission to begin dialing. Once w receives permission to dial, it will do so in a separate goroutine.
dialConnFor dials on behalf of w and delivers the result to w. dialConnFor has received permission to dial w.cm and is counted in t.connCount[w.cm.key()]. If the dial is cancelled or unsuccessful, dialConnFor decrements t.connCount[w.cm.key()].
func ( *Transport) ( *wantConn) {
	defer .afterDial()

	,  := .dialConn(.ctx, .cm)
	 := .tryDeliver(, )
pconn was not passed to w, or it is HTTP/2 and can be shared. Add to the idle connection pool.
		.putOrCloseIdleConn()
	}
	if  != nil {
		.decConnsPerHost(.key)
	}
}
decConnsPerHost decrements the per-host connection count for key, which may in turn give a different waiting goroutine permission to dial.
func ( *Transport) ( connectMethodKey) {
	if .MaxConnsPerHost <= 0 {
		return
	}

	.connsPerHostMu.Lock()
	defer .connsPerHostMu.Unlock()
	 := .connsPerHost[]
Shouldn't happen, but if it does, the counting is buggy and could easily lead to a silent deadlock, so report the problem loudly.
		panic("net/http: internal error: connCount underflow")
	}
Can we hand this count to a goroutine still waiting to dial? (Some goroutines on the wait list may have timed out or gotten a connection another way. If they're all gone, we don't want to kick off any spurious dial operations.)
	if  := .connsPerHostWait[]; .len() > 0 {
		 := false
		for .len() > 0 {
			 := .popFront()
			if .waiting() {
				go .dialConnFor()
				 = true
				break
			}
		}
		if .len() == 0 {
			delete(.connsPerHostWait, )
q is a value (like a slice), so we have to store the updated q back into the map.
			.connsPerHostWait[] = 
		}
		if  {
			return
		}
	}
Otherwise, decrement the recorded count.
	if --;  == 0 {
		delete(.connsPerHost, )
	} else {
		.connsPerHost[] = 
	}
}
Add TLS to a persistent connection, i.e. negotiate a TLS session. If pconn is already a TLS tunnel, this function establishes a nested TLS session inside the encrypted channel. The remote endpoint's name may be overridden by TLSClientConfig.ServerName.
Initiate TLS and check remote host name against certificate.
	 := cloneTLSConfig(.t.TLSClientConfig)
	if .ServerName == "" {
		.ServerName = 
	}
	if .cacheKey.onlyH1 {
		.NextProtos = nil
	}
	 := .conn
	 := tls.Client(, )
	 := make(chan error, 2)
	var  *time.Timer // for canceling TLS handshake
	if  := .t.TLSHandshakeTimeout;  != 0 {
		 = time.AfterFunc(, func() {
			 <- tlsHandshakeTimeoutError{}
		})
	}
	go func() {
		if  != nil && .TLSHandshakeStart != nil {
			.TLSHandshakeStart()
		}
		 := .Handshake()
		if  != nil {
			.Stop()
		}
		 <- 
	}()
	if  := <-;  != nil {
		.Close()
		if  != nil && .TLSHandshakeDone != nil {
			.TLSHandshakeDone(tls.ConnectionState{}, )
		}
		return 
	}
	 := .ConnectionState()
	if  != nil && .TLSHandshakeDone != nil {
		.TLSHandshakeDone(, nil)
	}
	.tlsState = &
	.conn = 
	return nil
}

type erringRoundTripper interface {
	RoundTripErr() error
}

func ( *Transport) ( context.Context,  connectMethod) ( *persistConn,  error) {
	 = &persistConn{
		t:             ,
		cacheKey:      .key(),
		reqch:         make(chan requestAndChan, 1),
		writech:       make(chan writeRequest, 1),
		closech:       make(chan struct{}),
		writeErrCh:    make(chan error, 1),
		writeLoopDone: make(chan struct{}),
	}
	 := httptrace.ContextClientTrace()
	 := func( error) error {
Return a typed error, per Issue 16997
			return &net.OpError{Op: "proxyconnect", Net: "tcp", Err: }
		}
		return 
	}
	if .scheme() == "https" && .hasCustomTLSDialer() {
		var  error
		.conn,  = .customDialTLS(, "tcp", .addr())
		if  != nil {
			return nil, ()
		}
Handshake here, in case DialTLS didn't. TLSNextProto below depends on it for knowing the connection state.
			if  != nil && .TLSHandshakeStart != nil {
				.TLSHandshakeStart()
			}
			if  := .Handshake();  != nil {
				go .conn.Close()
				if  != nil && .TLSHandshakeDone != nil {
					.TLSHandshakeDone(tls.ConnectionState{}, )
				}
				return nil, 
			}
			 := .ConnectionState()
			if  != nil && .TLSHandshakeDone != nil {
				.TLSHandshakeDone(, nil)
			}
			.tlsState = &
		}
	} else {
		,  := .dial(, "tcp", .addr())
		if  != nil {
			return nil, ()
		}
		.conn = 
		if .scheme() == "https" {
			var  string
			if , _,  = net.SplitHostPort(.addr());  != nil {
				return nil, ()
			}
			if  = .addTLS(, );  != nil {
				return nil, ()
			}
		}
	}
Proxy setup.
	switch {
Do nothing. Not using a proxy.
	case .proxyURL.Scheme == "socks5":
		 := .conn
		 := socksNewDialer("tcp", .RemoteAddr().String())
		if  := .proxyURL.User;  != nil {
			 := &socksUsernamePassword{
				Username: .Username(),
			}
			.Password, _ = .Password()
			.AuthMethods = []socksAuthMethod{
				socksAuthMethodNotRequired,
				socksAuthMethodUsernamePassword,
			}
			.Authenticate = .Authenticate
		}
		if ,  := .DialWithConn(, , "tcp", .targetAddr);  != nil {
			.Close()
			return nil, 
		}
	case .targetScheme == "http":
		.isProxy = true
		if  := .proxyAuth();  != "" {
			.mutateHeaderFunc = func( Header) {
				.Set("Proxy-Authorization", )
			}
		}
	case .targetScheme == "https":
		 := .conn
		var  Header
		if .GetProxyConnectHeader != nil {
			var  error
			,  = .GetProxyConnectHeader(, .proxyURL, .targetAddr)
			if  != nil {
				.Close()
				return nil, 
			}
		} else {
			 = .ProxyConnectHeader
		}
		if  == nil {
			 = make(Header)
		}
		if  := .proxyAuth();  != "" {
			 = .Clone()
			.Set("Proxy-Authorization", )
		}
		 := &Request{
			Method: "CONNECT",
			URL:    &url.URL{Opaque: .targetAddr},
			Host:   .targetAddr,
			Header: ,
		}
If there's no done channel (no deadline or cancellation from the caller possible), at least set some (long) timeout here. This will make sure we don't block forever and leak a goroutine if the connection stops replying after the TCP connect.
		 := 
		if .Done() == nil {
			,  := context.WithTimeout(, 1*time.Minute)
			defer ()
			 = 
		}

		 := make(chan struct{}) // closed after CONNECT write+read is done or fails
		var (
			 *Response
			  error // write or read error
Write the CONNECT request & read the response.
		go func() {
			defer close()
			 = .Write()
			if  != nil {
				return
Okay to use and discard buffered reader here, because TLS server will not speak until spoken to.
			 := bufio.NewReader()
			,  = ReadResponse(, )
		}()
		select {
		case <-.Done():
			.Close()
			<-
			return nil, .Err()
resp or err now set
		}
		if  != nil {
			.Close()
			return nil, 
		}
		if .StatusCode != 200 {
			 := strings.SplitN(.Status, " ", 2)
			.Close()
			if len() < 2 {
				return nil, errors.New("unknown status code")
			}
			return nil, errors.New([1])
		}
	}

	if .proxyURL != nil && .targetScheme == "https" {
		if  := .addTLS(.tlsHost(), );  != nil {
			return nil, 
		}
	}

	if  := .tlsState;  != nil && .NegotiatedProtocolIsMutual && .NegotiatedProtocol != "" {
		if ,  := .TLSNextProto[.NegotiatedProtocol];  {
			 := (.targetAddr, .conn.(*tls.Conn))
pconn.conn was closed by next (http2configureTransports.upgradeFn).
				return nil, .RoundTripErr()
			}
			return &persistConn{t: , cacheKey: .cacheKey, alt: }, nil
		}
	}

	.br = bufio.NewReaderSize(, .readBufferSize())
	.bw = bufio.NewWriterSize(persistConnWriter{}, .writeBufferSize())

	go .readLoop()
	go .writeLoop()
	return , nil
}
persistConnWriter is the io.Writer written to by pc.bw. It accumulates the number of bytes written to the underlying conn, so the retry logic can determine whether any bytes made it across the wire. This is exactly 1 pointer field wide so it can go into an interface without allocation.
type persistConnWriter struct {
	pc *persistConn
}

func ( persistConnWriter) ( []byte) ( int,  error) {
	,  = .pc.conn.Write()
	.pc.nwrite += int64()
	return
}
ReadFrom exposes persistConnWriter's underlying Conn to io.Copy and if the Conn implements io.ReaderFrom, it can take advantage of optimizations such as sendfile.
func ( persistConnWriter) ( io.Reader) ( int64,  error) {
	,  = io.Copy(.pc.conn, )
	.pc.nwrite += 
	return
}

var _ io.ReaderFrom = (*persistConnWriter)(nil)
connectMethod is the map key (in its String form) for keeping persistent TCP connections alive for subsequent HTTP requests. A connect method may be of the following types: connectMethod.key().String() Description ------------------------------ ------------------------- |http|foo.com http directly to server, no proxy |https|foo.com https directly to server, no proxy |https,h1|foo.com https directly to server w/o HTTP/2, no proxy http://proxy.com|https|foo.com http to proxy, then CONNECT to foo.com http://proxy.com|http http to proxy, http to anywhere after that socks5://proxy.com|http|foo.com socks5 to proxy, then http to foo.com socks5://proxy.com|https|foo.com socks5 to proxy, then https to foo.com https://proxy.com|https|foo.com https to proxy, then CONNECT to foo.com https://proxy.com|http https to proxy, http to anywhere after that
type connectMethod struct {
	_            incomparable
	proxyURL     *url.URL // nil for no proxy, else full proxy URL
If proxyURL specifies an http or https proxy, and targetScheme is http (not https), then targetAddr is not included in the connect method key, because the socket can be reused for different targetAddr values.
	targetAddr string
	onlyH1     bool // whether to disable HTTP/2 and force HTTP/1
}

func ( *connectMethod) () connectMethodKey {
	 := ""
	 := .targetAddr
	if .proxyURL != nil {
		 = .proxyURL.String()
		if (.proxyURL.Scheme == "http" || .proxyURL.Scheme == "https") && .targetScheme == "http" {
			 = ""
		}
	}
	return connectMethodKey{
		proxy:  ,
		scheme: .targetScheme,
		addr:   ,
		onlyH1: .onlyH1,
	}
}
scheme returns the first hop scheme: http, https, or socks5
func ( *connectMethod) () string {
	if .proxyURL != nil {
		return .proxyURL.Scheme
	}
	return .targetScheme
}
addr returns the first hop "host:port" to which we need to TCP connect.
func ( *connectMethod) () string {
	if .proxyURL != nil {
		return canonicalAddr(.proxyURL)
	}
	return .targetAddr
}
tlsHost returns the host name to match against the peer's TLS certificate.
func ( *connectMethod) () string {
	 := .targetAddr
	if hasPort() {
		 = [:strings.LastIndex(, ":")]
	}
	return 
}
connectMethodKey is the map key version of connectMethod, with a stringified proxy URL (or the empty string) instead of a pointer to a URL.
Only used by tests.
	var  string
	if .onlyH1 {
		 = ",h1"
	}
	return fmt.Sprintf("%s|%s%s|%s", .proxy, .scheme, , .addr)
}
persistConn wraps a connection, usually a persistent one (but may be used for non-keep-alive requests as well)
alt optionally specifies the TLS NextProto RoundTripper. This is used for HTTP/2 today and future protocols later. If it's non-nil, the rest of the fields are unused.
	alt RoundTripper

	t         *Transport
	cacheKey  connectMethodKey
	conn      net.Conn
	tlsState  *tls.ConnectionState
	br        *bufio.Reader       // from conn
	bw        *bufio.Writer       // to conn
	nwrite    int64               // bytes written
	reqch     chan requestAndChan // written by roundTrip; read by readLoop
	writech   chan writeRequest   // written by roundTrip; read by writeLoop
	closech   chan struct{}       // closed when conn closed
	isProxy   bool
	sawEOF    bool  // whether we've seen EOF from conn; owned by readLoop
writeErrCh passes the request write error (usually nil) from the writeLoop goroutine to the readLoop which passes it off to the res.Body reader, which then uses it to decide whether or not a connection can be reused. Issue 7569.
	writeErrCh chan error

	writeLoopDone chan struct{} // closed when write loop ends
Both guarded by Transport.idleMu:
	idleAt    time.Time   // time it last become idle
	idleTimer *time.Timer // holding an AfterFunc to close it

	mu                   sync.Mutex // guards following fields
	numExpectedResponses int
	closed               error // set non-nil when conn is closed, before closech is closed
	canceledErr          error // set non-nil if conn is canceled
	broken               bool  // an error has happened on this connection; marked broken so it's not reused.
mutateHeaderFunc is an optional func to modify extra headers on each outbound request before it's written. (the original Request given to RoundTrip is not modified)
	mutateHeaderFunc func(Header)
}

func ( *persistConn) () int64 {
	if  := .t.MaxResponseHeaderBytes;  != 0 {
		return 
	}
	return 10 << 20 // conservative default; same as http2
}

func ( *persistConn) ( []byte) ( int,  error) {
	if .readLimit <= 0 {
		return 0, fmt.Errorf("read limit of %d bytes exhausted", .maxHeaderResponseSize())
	}
	if int64(len()) > .readLimit {
		 = [:.readLimit]
	}
	,  = .conn.Read()
	if  == io.EOF {
		.sawEOF = true
	}
	.readLimit -= int64()
	return
}
isBroken reports whether this connection is in a known broken state.
func ( *persistConn) () bool {
	.mu.Lock()
	 := .closed != nil
	.mu.Unlock()
	return 
}
canceled returns non-nil if the connection was closed due to CancelRequest or due to context cancellation.
func ( *persistConn) () error {
	.mu.Lock()
	defer .mu.Unlock()
	return .canceledErr
}
isReused reports whether this connection has been used before.
func ( *persistConn) () bool {
	.mu.Lock()
	 := .reused
	.mu.Unlock()
	return 
}

func ( *persistConn) ( time.Time) ( httptrace.GotConnInfo) {
	.mu.Lock()
	defer .mu.Unlock()
	.Reused = .reused
	.Conn = .conn
	.WasIdle = true
	if !.IsZero() {
		.IdleTime = time.Since()
	}
	return
}

func ( *persistConn) ( error) {
	.mu.Lock()
	defer .mu.Unlock()
	.canceledErr = 
	.closeLocked(errRequestCanceled)
}
closeConnIfStillIdle closes the connection if it's still sitting idle. This is what's called by the persistConn's idleTimer, and is run in its own goroutine.
func ( *persistConn) () {
	 := .t
	.idleMu.Lock()
	defer .idleMu.Unlock()
Not idle.
mapRoundTripError returns the appropriate error value for persistConn.roundTrip. The provided err is the first error that (*persistConn).roundTrip happened to receive from its select statement. The startBytesWritten value should be the value of pc.nwrite before the roundTrip started writing the request.
func ( *persistConn) ( *transportRequest,  int64,  error) error {
	if  == nil {
		return nil
	}
Wait for the writeLoop goroutine to terminate to avoid data races on callers who mutate the request on failure. When resc in pc.roundTrip and hence rc.ch receives a responseAndError with a non-nil error it implies that the persistConn is either closed or closing. Waiting on pc.writeLoopDone is hence safe as all callers close closech which in turn ensures writeLoop returns.
If the request was canceled, that's better than network failures that were likely the result of tearing down the connection.
	if  := .canceled();  != nil {
		return 
	}
See if an error was set explicitly.
	.mu.Lock()
	 := .err
	.mu.Unlock()
	if  != nil {
		return 
	}

Don't decorate
		return 
	}

Don't decorate
		return 
	}
	if .isBroken() {
		if .nwrite ==  {
			return nothingWrittenError{}
		}
		return fmt.Errorf("net/http: HTTP/1.x transport connection broken: %v", )
	}
	return 
}
errCallerOwnsConn is an internal sentinel error used when we hand off a writable response.Body to the caller. We use this to prevent closing a net.Conn that is now owned by the caller.
var errCallerOwnsConn = errors.New("read loop ending; caller owns writable underlying conn")

func ( *persistConn) () {
	 := errReadLoopExiting // default value, if not changed below
	defer func() {
		.close()
		.t.removeIdleConn()
	}()

	 := func( *httptrace.ClientTrace) bool {
		if  := .t.tryPutIdleConn();  != nil {
			 = 
			if  != nil && .PutIdleConn != nil &&  != errKeepAlivesDisabled {
				.PutIdleConn()
			}
			return false
		}
		if  != nil && .PutIdleConn != nil {
			.PutIdleConn(nil)
		}
		return true
	}
eofc is used to block caller goroutines reading from Response.Body at EOF until this goroutines has (potentially) added the connection back to the idle pool.
	 := make(chan struct{})
	defer close() // unblock reader on errors
Read this once, before loop starts. (to avoid races in tests)
	testHookMu.Lock()
	 := testHookReadLoopBeforeNextRead
	testHookMu.Unlock()

	 := true
	for  {
		.readLimit = .maxHeaderResponseSize()
		,  := .br.Peek(1)

		.mu.Lock()
		if .numExpectedResponses == 0 {
			.readLoopPeekFailLocked()
			.mu.Unlock()
			return
		}
		.mu.Unlock()

		 := <-.reqch
		 := httptrace.ContextClientTrace(.req.Context())

		var  *Response
		if  == nil {
			,  = .readResponse(, )
		} else {
			 = transportReadFromServerError{}
			 = 
		}

		if  != nil {
			if .readLimit <= 0 {
				 = fmt.Errorf("net/http: server response headers exceeded %d bytes; aborted", .maxHeaderResponseSize())
			}

			select {
			case .ch <- responseAndError{err: }:
			case <-.callerGone:
				return
			}
			return
		}
		.readLimit = maxInt64 // effectively no limit for response bodies

		.mu.Lock()
		.numExpectedResponses--
		.mu.Unlock()

		 := .bodyIsWritable()
		 := .req.Method != "HEAD" && .ContentLength != 0

Don't do keep-alive on error if either party requested a close or we get an unexpected informational (1xx) response. StatusCode 100 is already handled above.
			 = false
		}

		if ! ||  {
			 := .t.replaceReqCanceler(.cancelKey, nil)
Put the idle conn back into the pool before we send the response so if they process it quickly and make another request, they'll get this same conn. But we use the unbuffered channel 'rc' to guarantee that persistConn.roundTrip got out of its select potentially waiting for this persistConn to close.
			 =  &&
				!.sawEOF &&
				.wroteRequest() &&
				 && ()

			if  {
				 = errCallerOwnsConn
			}

			select {
			case .ch <- responseAndError{res: }:
			case <-.callerGone:
				return
			}
Now that they've read from the unbuffered channel, they're safely out of the select that also waits on this goroutine to die, so we're allowed to exit now if needed (if alive is false)
			()
			continue
		}

		 := make(chan bool, 2)
		 := &bodyEOFSignal{
			body: .Body,
			earlyCloseFn: func() error {
				 <- false
				<- // will be closed by deferred call at the end of the function
				return nil

			},
			fn: func( error) error {
				 :=  == io.EOF
				 <- 
				if  {
					<- // see comment above eofc declaration
				} else if  != nil {
					if  := .canceled();  != nil {
						return 
					}
				}
				return 
			},
		}

		.Body = 
		if .addedGzip && strings.EqualFold(.Header.Get("Content-Encoding"), "gzip") {
			.Body = &gzipReader{body: }
			.Header.Del("Content-Encoding")
			.Header.Del("Content-Length")
			.ContentLength = -1
			.Uncompressed = true
		}

		select {
		case .ch <- responseAndError{res: }:
		case <-.callerGone:
			return
		}
Before looping back to the top of this function and peeking on the bufio.Reader, wait for the caller goroutine to finish reading the response body. (or for cancellation or death)
		select {
		case  := <-:
			 := .t.replaceReqCanceler(.cancelKey, nil) // before pc might return to idle pool
			 =  &&
				 &&
				!.sawEOF &&
				.wroteRequest() &&
				 && ()
			if  {
				 <- struct{}{}
			}
		case <-.req.Cancel:
			 = false
			.t.CancelRequest(.req)
		case <-.req.Context().Done():
			 = false
			.t.cancelRequest(.cancelKey, .req.Context().Err())
		case <-.closech:
			 = false
		}

		()
	}
}

func ( *persistConn) ( error) {
	if .closed != nil {
		return
	}
	if  := .br.Buffered();  > 0 {
		,  := .br.Peek()
		if is408Message() {
			.closeLocked(errServerClosedIdle)
			return
		} else {
			log.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v", , )
		}
	}
common case.
		.closeLocked(errServerClosedIdle)
	} else {
		.closeLocked(fmt.Errorf("readLoopPeekFailLocked: %v", ))
	}
}
is408Message reports whether buf has the prefix of an HTTP 408 Request Timeout response. See golang.org/issue/32310.
func ( []byte) bool {
	if len() < len("HTTP/1.x 408") {
		return false
	}
	if string([:7]) != "HTTP/1." {
		return false
	}
	return string([8:12]) == " 408"
}
readResponse reads an HTTP response (or two, in the case of "Expect: 100-continue") from the server. It returns the final non-100 one. trace is optional.
func ( *persistConn) ( requestAndChan,  *httptrace.ClientTrace) ( *Response,  error) {
	if  != nil && .GotFirstResponseByte != nil {
		if ,  := .br.Peek(1);  == nil && len() == 1 {
			.GotFirstResponseByte()
		}
	}
	 := 0               // number of informational 1xx headers received
	const  = 5 // arbitrary bound on number of informational responses

	 := .continueCh
	for {
		,  = ReadResponse(.br, .req)
		if  != nil {
			return
		}
		 := .StatusCode
		if  != nil {
			if  == 100 {
				if  != nil && .Got100Continue != nil {
					.Got100Continue()
				}
				 <- struct{}{}
				 = nil
			} else if  >= 200 {
				close()
				 = nil
			}
		}
treat 101 as a terminal status, see issue 26161
		 :=  &&  != StatusSwitchingProtocols
		if  {
			++
			if  >  {
				return nil, errors.New("net/http: too many 1xx informational responses")
			}
			.readLimit = .maxHeaderResponseSize() // reset the limit
			if  != nil && .Got1xxResponse != nil {
				if  := .Got1xxResponse(, textproto.MIMEHeader(.Header));  != nil {
					return nil, 
				}
			}
			continue
		}
		break
	}
	if .isProtocolSwitch() {
		.Body = newReadWriteCloserBody(.br, .conn)
	}

	.TLS = .tlsState
	return
}
waitForContinue returns the function to block until any response, timeout or connection close. After any of them, the function returns a bool which indicates if the body should be sent.
func ( *persistConn) ( <-chan struct{}) func() bool {
	if  == nil {
		return nil
	}
	return func() bool {
		 := time.NewTimer(.t.ExpectContinueTimeout)
		defer .Stop()

		select {
		case ,  := <-:
			return 
		case <-.C:
			return true
		case <-.closech:
			return false
		}
	}
}

func ( *bufio.Reader,  io.ReadWriteCloser) io.ReadWriteCloser {
	 := &readWriteCloserBody{ReadWriteCloser: }
	if .Buffered() != 0 {
		.br = 
	}
	return 
}
readWriteCloserBody is the Response.Body type used when we want to give users write access to the Body through the underlying connection (TCP, unless using custom dialers). This is then the concrete type for a Response.Body on the 101 Switching Protocols response, as used by WebSockets, h2c, etc.
type readWriteCloserBody struct {
	_  incomparable
	br *bufio.Reader // used until empty
	io.ReadWriteCloser
}

func ( *readWriteCloserBody) ( []byte) ( int,  error) {
	if .br != nil {
		if  := .br.Buffered(); len() >  {
			 = [:]
		}
		,  = .br.Read()
		if .br.Buffered() == 0 {
			.br = nil
		}
		return , 
	}
	return .ReadWriteCloser.Read()
}
nothingWrittenError wraps a write errors which ended up writing zero bytes.
type nothingWrittenError struct {
	error
}

func ( *persistConn) () {
	defer close(.writeLoopDone)
	for {
		select {
		case  := <-.writech:
			 := .nwrite
			 := .req.Request.write(.bw, .isProxy, .req.extra, .waitForContinue(.continueCh))
			if ,  := .(requestBodyReadError);  {
Errors reading from the user's Request.Body are high priority. Set it here before sending on the channels below or calling pc.close() which tears down connections and causes other errors.
				.req.setError()
			}
			if  == nil {
				 = .bw.Flush()
			}
			if  != nil {
				if .nwrite ==  {
					 = nothingWrittenError{}
				}
			}
			.writeErrCh <-  // to the body reader, which might recycle us
			.ch <-          // to the roundTrip function
			if  != nil {
				.close()
				return
			}
		case <-.closech:
			return
		}
	}
}
maxWriteWaitBeforeConnReuse is how long the a Transport RoundTrip will wait to see the Request's Body.Write result after getting a response from the server. See comments in (*persistConn).wroteRequest.
wroteRequest is a check before recycling a connection that the previous write (from writeLoop above) happened and was successful.
Common case: the write happened well before the response, so avoid creating a timer.
		return  == nil
Rare case: the request was written in writeLoop above but before it could send to pc.writeErrCh, the reader read it all, processed it, and called us here. In this case, give the write goroutine a bit of time to finish its send. Less rare case: We also get here in the legitimate case of Issue 7569, where the writer is still writing (or stalled), but the server has already replied. In this case, we don't want to wait too long, and we want to return false so this connection isn't re-used.
		 := time.NewTimer(maxWriteWaitBeforeConnReuse)
		defer .Stop()
		select {
		case  := <-.writeErrCh:
			return  == nil
		case <-.C:
			return false
		}
	}
}
responseAndError is how the goroutine reading from an HTTP/1 server communicates with the goroutine doing the RoundTrip.
type responseAndError struct {
	_   incomparable
	res *Response // else use this response (see res method)
	err error
}

type requestAndChan struct {
	_         incomparable
	req       *Request
	cancelKey cancelKey
	ch        chan responseAndError // unbuffered; always send in select on callerGone
whether the Transport (as opposed to the user client code) added the Accept-Encoding gzip header. If the Transport set it, only then do we transparently decode the gzip.
Optional blocking chan for Expect: 100-continue (for send). If the request has an "Expect: 100-continue" header and the server responds 100 Continue, readLoop send a value to writeLoop via this chan.
	continueCh chan<- struct{}

	callerGone <-chan struct{} // closed when roundTrip caller has returned
}
A writeRequest is sent by the readLoop's goroutine to the writeLoop's goroutine to write a request while the read loop concurrently waits on both the write response and the server's reply.
type writeRequest struct {
	req *transportRequest
	ch  chan<- error
Optional blocking chan for Expect: 100-continue (for receive). If not nil, writeLoop blocks sending request body until it receives from this chan.
	continueCh <-chan struct{}
}

type httpError struct {
	err     string
	timeout bool
}

func ( *httpError) () string   { return .err }
func ( *httpError) () bool   { return .timeout }
func ( *httpError) () bool { return true }

var errTimeout error = &httpError{err: "net/http: timeout awaiting response headers", timeout: true}
errRequestCanceled is set to be identical to the one from h2 to facilitate testing.
var errRequestCanceled = http2errRequestCanceled
var errRequestCanceledConn = errors.New("net/http: request canceled while waiting for connection") // TODO: unify?

func () {}
Ask for a compressed version if the caller didn't set their own value for Accept-Encoding. We only attempt to uncompress the gzip stream if we were the layer that requested it.
	 := false
	if !.t.DisableCompression &&
		.Header.Get("Accept-Encoding") == "" &&
		.Header.Get("Range") == "" &&
Request gzip only, not deflate. Deflate is ambiguous and not as universally supported anyway. See: https://zlib.net/zlib_faq.html#faq39 Note that we don't request this for HEAD requests, due to a bug in nginx: https://trac.nginx.org/nginx/ticket/358 https://golang.org/issue/5522 We don't request gzip if the request is for a range, since auto-decoding a portion of a gzipped document will just fail anyway. See https://golang.org/issue/8923
		 = true
		.extraHeaders().Set("Accept-Encoding", "gzip")
	}

	var  chan struct{}
	if .ProtoAtLeast(1, 1) && .Body != nil && .expectsContinue() {
		 = make(chan struct{}, 1)
	}

	if .t.DisableKeepAlives &&
		!.wantsClose() &&
		!isProtocolSwitchHeader(.Header) {
		.extraHeaders().Set("Connection", "close")
	}

	 := make(chan struct{})
	defer close()

	defer func() {
		if  != nil {
			.t.setReqCanceler(.cancelKey, nil)
		}
	}()

	const  = false
Write the request concurrently with waiting for a response, in case the server decides to reply before reading our full request body.
	 := .nwrite
	 := make(chan error, 1)
	.writech <- writeRequest{, , }

	 := make(chan responseAndError)
	.reqch <- requestAndChan{
		req:        .Request,
		cancelKey:  .cancelKey,
		ch:         ,
		addedGzip:  ,
		continueCh: ,
		callerGone: ,
	}

	var  <-chan time.Time
	 := .Request.Cancel
	 := .Context().Done()
	 := .closech
	 := false
	for {
		testHookWaitResLoop()
		select {
		case  := <-:
			if  {
				.logf("writeErrCh resv: %T/%#v", , )
			}
			if  != nil {
				.close(fmt.Errorf("write error: %v", ))
				return nil, .mapRoundTripError(, , )
			}
			if  := .t.ResponseHeaderTimeout;  > 0 {
				if  {
					.logf("starting timer for %v", )
				}
				 := time.NewTimer()
				defer .Stop() // prevent leaks
				 = .C
			}
		case <-:
			 = nil
			if  || .t.replaceReqCanceler(.cancelKey, nil) {
				if  {
					.logf("closech recv: %T %#v", .closed, .closed)
				}
				return nil, .mapRoundTripError(, , .closed)
			}
		case <-:
			if  {
				.logf("timeout waiting for response headers.")
			}
			.close(errTimeout)
			return nil, errTimeout
		case  := <-:
			if (.res == nil) == (.err == nil) {
				panic(fmt.Sprintf("internal error: exactly one of res or err should be set; nil=%v", .res == nil))
			}
			if  {
				.logf("resc recv: %p, %T/%#v", .res, .err, .err)
			}
			if .err != nil {
				return nil, .mapRoundTripError(, , .err)
			}
			return .res, nil
		case <-:
			 = .t.cancelRequest(.cancelKey, errRequestCanceled)
			 = nil
		case <-:
			 = .t.cancelRequest(.cancelKey, .Context().Err())
			 = nil
			 = nil
		}
	}
}
tLogKey is a context WithValue key for test debugging contexts containing a t.Logf func. See export_test.go's Request.WithT method.
type tLogKey struct{}

func ( *transportRequest) ( string,  ...interface{}) {
	if ,  := .Request.Context().Value(tLogKey{}).(func(string, ...interface{}));  {
		(time.Now().Format(time.RFC3339Nano)+": "+, ...)
	}
}
markReused marks this connection as having been successfully used for a request and response.
func ( *persistConn) () {
	.mu.Lock()
	.reused = true
	.mu.Unlock()
}
close closes the underlying TCP connection and closes the pc.closech channel. The provided err is only for testing and debugging; in normal circumstances it should never be seen by users.
func ( *persistConn) ( error) {
	.mu.Lock()
	defer .mu.Unlock()
	.closeLocked()
}

func ( *persistConn) ( error) {
	if  == nil {
		panic("nil error")
	}
	.broken = true
	if .closed == nil {
		.closed = 
Close HTTP/1 (pc.alt == nil) connection. HTTP/2 closes its connection itself.
		if .alt == nil {
			if  != errCallerOwnsConn {
				.conn.Close()
			}
			close(.closech)
		}
	}
	.mutateHeaderFunc = nil
}

var portMap = map[string]string{
	"http":   "80",
	"https":  "443",
	"socks5": "1080",
}
canonicalAddr returns url.Host but always with a ":port" suffix
func ( *url.URL) string {
	 := .Hostname()
	if ,  := idnaASCII();  == nil {
		 = 
	}
	 := .Port()
	if  == "" {
		 = portMap[.Scheme]
	}
	return net.JoinHostPort(, )
}
bodyEOFSignal is used by the HTTP/1 transport when reading response bodies to make sure we see the end of a response body before proceeding and reading on the connection again. It wraps a ReadCloser but runs fn (if non-nil) at most once, right before its final (error-producing) Read or Close call returns. fn should return the new error to return from Read or Close. If earlyCloseFn is non-nil and Close is called before io.EOF is seen, earlyCloseFn is called instead of fn, and its return value is the return value from Close.
type bodyEOFSignal struct {
	body         io.ReadCloser
	mu           sync.Mutex        // guards following 4 fields
	closed       bool              // whether Close has been called
	rerr         error             // sticky Read error
	fn           func(error) error // err will be nil on Read io.EOF
	earlyCloseFn func() error      // optional alt Close func used if io.EOF not seen
}

var errReadOnClosedResBody = errors.New("http: read on closed response body")

func ( *bodyEOFSignal) ( []byte) ( int,  error) {
	.mu.Lock()
	,  := .closed, .rerr
	.mu.Unlock()
	if  {
		return 0, errReadOnClosedResBody
	}
	if  != nil {
		return 0, 
	}

	,  = .body.Read()
	if  != nil {
		.mu.Lock()
		defer .mu.Unlock()
		if .rerr == nil {
			.rerr = 
		}
		 = .condfn()
	}
	return
}

func ( *bodyEOFSignal) () error {
	.mu.Lock()
	defer .mu.Unlock()
	if .closed {
		return nil
	}
	.closed = true
	if .earlyCloseFn != nil && .rerr != io.EOF {
		return .earlyCloseFn()
	}
	 := .body.Close()
	return .condfn()
}
caller must hold es.mu.
func ( *bodyEOFSignal) ( error) error {
	if .fn == nil {
		return 
	}
	 = .fn()
	.fn = nil
	return 
}
gzipReader wraps a response body so it can lazily call gzip.NewReader on the first call to Read
type gzipReader struct {
	_    incomparable
	body *bodyEOFSignal // underlying HTTP/1 response body framing
	zr   *gzip.Reader   // lazily-initialized gzip reader
	zerr error          // any error from gzip.NewReader; sticky
}

func ( *gzipReader) ( []byte) ( int,  error) {
	if .zr == nil {
		if .zerr == nil {
			.zr, .zerr = gzip.NewReader(.body)
		}
		if .zerr != nil {
			return 0, .zerr
		}
	}

	.body.mu.Lock()
	if .body.closed {
		 = errReadOnClosedResBody
	}
	.body.mu.Unlock()

	if  != nil {
		return 0, 
	}
	return .zr.Read()
}

func ( *gzipReader) () error {
	return .body.Close()
}

type tlsHandshakeTimeoutError struct{}

func (tlsHandshakeTimeoutError) () bool   { return true }
func (tlsHandshakeTimeoutError) () bool { return true }
func (tlsHandshakeTimeoutError) () string   { return "net/http: TLS handshake timeout" }
fakeLocker is a sync.Locker which does nothing. It's used to guard test-only fields when not under test, to avoid runtime atomic overhead.
type fakeLocker struct{}

func (fakeLocker) ()   {}
func (fakeLocker) () {}
cloneTLSConfig returns a shallow clone of cfg, or a new zero tls.Config if cfg is nil. This is safe to call even if cfg is in active use by a TLS client or server.
func ( *tls.Config) *tls.Config {
	if  == nil {
		return &tls.Config{}
	}
	return .Clone()
}

type connLRU struct {
	ll *list.List // list.Element.Value type is of *persistConn
	m  map[*persistConn]*list.Element
}
add adds pc to the head of the linked list.
func ( *connLRU) ( *persistConn) {
	if .ll == nil {
		.ll = list.New()
		.m = make(map[*persistConn]*list.Element)
	}
	 := .ll.PushFront()
	if ,  := .m[];  {
		panic("persistConn was already in LRU")
	}
	.m[] = 
}

func ( *connLRU) () *persistConn {
	 := .ll.Back()
	 := .Value.(*persistConn)
	.ll.Remove()
	delete(.m, )
	return 
}
remove removes pc from cl.
func ( *connLRU) ( *persistConn) {
	if ,  := .m[];  {
		.ll.Remove()
		delete(.m, )
	}
}
len returns the number of items in the cache.
func ( *connLRU) () int {
	return len(.m)