github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/pkg/net/http/transport.go (about)

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // HTTP client implementation. See RFC 2616.
     6  //
     7  // This is the low-level Transport implementation of RoundTripper.
     8  // The high-level interface is in client.go.
     9  
    10  package http
    11  
    12  import (
    13  	"bufio"
    14  	"compress/gzip"
    15  	"crypto/tls"
    16  	"errors"
    17  	"fmt"
    18  	"io"
    19  	"log"
    20  	"net"
    21  	"net/url"
    22  	"os"
    23  	"strings"
    24  	"sync"
    25  	"time"
    26  )
    27  
    28  // DefaultTransport is the default implementation of Transport and is
    29  // used by DefaultClient. It establishes network connections as needed
    30  // and caches them for reuse by subsequent calls. It uses HTTP proxies
    31  // as directed by the $HTTP_PROXY and $NO_PROXY (or $http_proxy and
    32  // $no_proxy) environment variables.
    33  var DefaultTransport RoundTripper = &Transport{
    34  	Proxy: ProxyFromEnvironment,
    35  	Dial: (&net.Dialer{
    36  		Timeout:   30 * time.Second,
    37  		KeepAlive: 30 * time.Second,
    38  	}).Dial,
    39  	TLSHandshakeTimeout: 10 * time.Second,
    40  }
    41  
    42  // DefaultMaxIdleConnsPerHost is the default value of Transport's
    43  // MaxIdleConnsPerHost.
    44  const DefaultMaxIdleConnsPerHost = 2
    45  
    46  // Transport is an implementation of RoundTripper that supports http,
    47  // https, and http proxies (for either http or https with CONNECT).
    48  // Transport can also cache connections for future re-use.
    49  type Transport struct {
    50  	idleMu      sync.Mutex
    51  	idleConn    map[connectMethodKey][]*persistConn
    52  	idleConnCh  map[connectMethodKey]chan *persistConn
    53  	reqMu       sync.Mutex
    54  	reqCanceler map[*Request]func()
    55  	altMu       sync.RWMutex
    56  	altProto    map[string]RoundTripper // nil or map of URI scheme => RoundTripper
    57  
    58  	// Proxy specifies a function to return a proxy for a given
    59  	// Request. If the function returns a non-nil error, the
    60  	// request is aborted with the provided error.
    61  	// If Proxy is nil or returns a nil *URL, no proxy is used.
    62  	Proxy func(*Request) (*url.URL, error)
    63  
    64  	// Dial specifies the dial function for creating TCP
    65  	// connections.
    66  	// If Dial is nil, net.Dial is used.
    67  	Dial func(network, addr string) (net.Conn, error)
    68  
    69  	// TLSClientConfig specifies the TLS configuration to use with
    70  	// tls.Client. If nil, the default configuration is used.
    71  	TLSClientConfig *tls.Config
    72  
    73  	// TLSHandshakeTimeout specifies the maximum amount of time waiting to
    74  	// wait for a TLS handshake. Zero means no timeout.
    75  	TLSHandshakeTimeout time.Duration
    76  
    77  	// DisableKeepAlives, if true, prevents re-use of TCP connections
    78  	// between different HTTP requests.
    79  	DisableKeepAlives bool
    80  
    81  	// DisableCompression, if true, prevents the Transport from
    82  	// requesting compression with an "Accept-Encoding: gzip"
    83  	// request header when the Request contains no existing
    84  	// Accept-Encoding value. If the Transport requests gzip on
    85  	// its own and gets a gzipped response, it's transparently
    86  	// decoded in the Response.Body. However, if the user
    87  	// explicitly requested gzip it is not automatically
    88  	// uncompressed.
    89  	DisableCompression bool
    90  
    91  	// MaxIdleConnsPerHost, if non-zero, controls the maximum idle
    92  	// (keep-alive) to keep per-host.  If zero,
    93  	// DefaultMaxIdleConnsPerHost is used.
    94  	MaxIdleConnsPerHost int
    95  
    96  	// ResponseHeaderTimeout, if non-zero, specifies the amount of
    97  	// time to wait for a server's response headers after fully
    98  	// writing the request (including its body, if any). This
    99  	// time does not include the time to read the response body.
   100  	ResponseHeaderTimeout time.Duration
   101  
   102  	// TODO: tunable on global max cached connections
   103  	// TODO: tunable on timeout on cached connections
   104  }
   105  
   106  // ProxyFromEnvironment returns the URL of the proxy to use for a
   107  // given request, as indicated by the environment variables
   108  // $HTTP_PROXY and $NO_PROXY (or $http_proxy and $no_proxy).
   109  // An error is returned if the proxy environment is invalid.
   110  // A nil URL and nil error are returned if no proxy is defined in the
   111  // environment, or a proxy should not be used for the given request.
   112  //
   113  // As a special case, if req.URL.Host is "localhost" (with or without
   114  // a port number), then a nil URL and nil error will be returned.
   115  func ProxyFromEnvironment(req *Request) (*url.URL, error) {
   116  	proxy := httpProxyEnv.Get()
   117  	if proxy == "" {
   118  		return nil, nil
   119  	}
   120  	if !useProxy(canonicalAddr(req.URL)) {
   121  		return nil, nil
   122  	}
   123  	proxyURL, err := url.Parse(proxy)
   124  	if err != nil || !strings.HasPrefix(proxyURL.Scheme, "http") {
   125  		// proxy was bogus. Try prepending "http://" to it and
   126  		// see if that parses correctly. If not, we fall
   127  		// through and complain about the original one.
   128  		if proxyURL, err := url.Parse("http://" + proxy); err == nil {
   129  			return proxyURL, nil
   130  		}
   131  	}
   132  	if err != nil {
   133  		return nil, fmt.Errorf("invalid proxy address %q: %v", proxy, err)
   134  	}
   135  	return proxyURL, nil
   136  }
   137  
   138  // ProxyURL returns a proxy function (for use in a Transport)
   139  // that always returns the same URL.
   140  func ProxyURL(fixedURL *url.URL) func(*Request) (*url.URL, error) {
   141  	return func(*Request) (*url.URL, error) {
   142  		return fixedURL, nil
   143  	}
   144  }
   145  
   146  // transportRequest is a wrapper around a *Request that adds
   147  // optional extra headers to write.
   148  type transportRequest struct {
   149  	*Request        // original request, not to be mutated
   150  	extra    Header // extra headers to write, or nil
   151  }
   152  
   153  func (tr *transportRequest) extraHeaders() Header {
   154  	if tr.extra == nil {
   155  		tr.extra = make(Header)
   156  	}
   157  	return tr.extra
   158  }
   159  
   160  // RoundTrip implements the RoundTripper interface.
   161  //
   162  // For higher-level HTTP client support (such as handling of cookies
   163  // and redirects), see Get, Post, and the Client type.
   164  func (t *Transport) RoundTrip(req *Request) (resp *Response, err error) {
   165  	if req.URL == nil {
   166  		req.closeBody()
   167  		return nil, errors.New("http: nil Request.URL")
   168  	}
   169  	if req.Header == nil {
   170  		req.closeBody()
   171  		return nil, errors.New("http: nil Request.Header")
   172  	}
   173  	if req.URL.Scheme != "http" && req.URL.Scheme != "https" {
   174  		t.altMu.RLock()
   175  		var rt RoundTripper
   176  		if t.altProto != nil {
   177  			rt = t.altProto[req.URL.Scheme]
   178  		}
   179  		t.altMu.RUnlock()
   180  		if rt == nil {
   181  			req.closeBody()
   182  			return nil, &badStringError{"unsupported protocol scheme", req.URL.Scheme}
   183  		}
   184  		return rt.RoundTrip(req)
   185  	}
   186  	if req.URL.Host == "" {
   187  		req.closeBody()
   188  		return nil, errors.New("http: no Host in request URL")
   189  	}
   190  	treq := &transportRequest{Request: req}
   191  	cm, err := t.connectMethodForRequest(treq)
   192  	if err != nil {
   193  		req.closeBody()
   194  		return nil, err
   195  	}
   196  
   197  	// Get the cached or newly-created connection to either the
   198  	// host (for http or https), the http proxy, or the http proxy
   199  	// pre-CONNECTed to https server.  In any case, we'll be ready
   200  	// to send it requests.
   201  	pconn, err := t.getConn(req, cm)
   202  	if err != nil {
   203  		t.setReqCanceler(req, nil)
   204  		req.closeBody()
   205  		return nil, err
   206  	}
   207  
   208  	return pconn.roundTrip(treq)
   209  }
   210  
   211  // RegisterProtocol registers a new protocol with scheme.
   212  // The Transport will pass requests using the given scheme to rt.
   213  // It is rt's responsibility to simulate HTTP request semantics.
   214  //
   215  // RegisterProtocol can be used by other packages to provide
   216  // implementations of protocol schemes like "ftp" or "file".
   217  func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper) {
   218  	if scheme == "http" || scheme == "https" {
   219  		panic("protocol " + scheme + " already registered")
   220  	}
   221  	t.altMu.Lock()
   222  	defer t.altMu.Unlock()
   223  	if t.altProto == nil {
   224  		t.altProto = make(map[string]RoundTripper)
   225  	}
   226  	if _, exists := t.altProto[scheme]; exists {
   227  		panic("protocol " + scheme + " already registered")
   228  	}
   229  	t.altProto[scheme] = rt
   230  }
   231  
   232  // CloseIdleConnections closes any connections which were previously
   233  // connected from previous requests but are now sitting idle in
   234  // a "keep-alive" state. It does not interrupt any connections currently
   235  // in use.
   236  func (t *Transport) CloseIdleConnections() {
   237  	t.idleMu.Lock()
   238  	m := t.idleConn
   239  	t.idleConn = nil
   240  	t.idleConnCh = nil
   241  	t.idleMu.Unlock()
   242  	for _, conns := range m {
   243  		for _, pconn := range conns {
   244  			pconn.close()
   245  		}
   246  	}
   247  }
   248  
   249  // CancelRequest cancels an in-flight request by closing its
   250  // connection.
   251  func (t *Transport) CancelRequest(req *Request) {
   252  	t.reqMu.Lock()
   253  	cancel := t.reqCanceler[req]
   254  	t.reqMu.Unlock()
   255  	if cancel != nil {
   256  		cancel()
   257  	}
   258  }
   259  
   260  //
   261  // Private implementation past this point.
   262  //
   263  
   264  var (
   265  	httpProxyEnv = &envOnce{
   266  		names: []string{"HTTP_PROXY", "http_proxy"},
   267  	}
   268  	noProxyEnv = &envOnce{
   269  		names: []string{"NO_PROXY", "no_proxy"},
   270  	}
   271  )
   272  
   273  // envOnce looks up an environment variable (optionally by multiple
   274  // names) once. It mitigates expensive lookups on some platforms
   275  // (e.g. Windows).
   276  type envOnce struct {
   277  	names []string
   278  	once  sync.Once
   279  	val   string
   280  }
   281  
   282  func (e *envOnce) Get() string {
   283  	e.once.Do(e.init)
   284  	return e.val
   285  }
   286  
   287  func (e *envOnce) init() {
   288  	for _, n := range e.names {
   289  		e.val = os.Getenv(n)
   290  		if e.val != "" {
   291  			return
   292  		}
   293  	}
   294  }
   295  
   296  // reset is used by tests
   297  func (e *envOnce) reset() {
   298  	e.once = sync.Once{}
   299  	e.val = ""
   300  }
   301  
   302  func (t *Transport) connectMethodForRequest(treq *transportRequest) (cm connectMethod, err error) {
   303  	cm.targetScheme = treq.URL.Scheme
   304  	cm.targetAddr = canonicalAddr(treq.URL)
   305  	if t.Proxy != nil {
   306  		cm.proxyURL, err = t.Proxy(treq.Request)
   307  	}
   308  	return cm, nil
   309  }
   310  
   311  // proxyAuth returns the Proxy-Authorization header to set
   312  // on requests, if applicable.
   313  func (cm *connectMethod) proxyAuth() string {
   314  	if cm.proxyURL == nil {
   315  		return ""
   316  	}
   317  	if u := cm.proxyURL.User; u != nil {
   318  		username := u.Username()
   319  		password, _ := u.Password()
   320  		return "Basic " + basicAuth(username, password)
   321  	}
   322  	return ""
   323  }
   324  
   325  // putIdleConn adds pconn to the list of idle persistent connections awaiting
   326  // a new request.
   327  // If pconn is no longer needed or not in a good state, putIdleConn
   328  // returns false.
   329  func (t *Transport) putIdleConn(pconn *persistConn) bool {
   330  	if t.DisableKeepAlives || t.MaxIdleConnsPerHost < 0 {
   331  		pconn.close()
   332  		return false
   333  	}
   334  	if pconn.isBroken() {
   335  		return false
   336  	}
   337  	key := pconn.cacheKey
   338  	max := t.MaxIdleConnsPerHost
   339  	if max == 0 {
   340  		max = DefaultMaxIdleConnsPerHost
   341  	}
   342  	t.idleMu.Lock()
   343  
   344  	waitingDialer := t.idleConnCh[key]
   345  	select {
   346  	case waitingDialer <- pconn:
   347  		// We're done with this pconn and somebody else is
   348  		// currently waiting for a conn of this type (they're
   349  		// actively dialing, but this conn is ready
   350  		// first). Chrome calls this socket late binding.  See
   351  		// https://insouciant.org/tech/connection-management-in-chromium/
   352  		t.idleMu.Unlock()
   353  		return true
   354  	default:
   355  		if waitingDialer != nil {
   356  			// They had populated this, but their dial won
   357  			// first, so we can clean up this map entry.
   358  			delete(t.idleConnCh, key)
   359  		}
   360  	}
   361  	if t.idleConn == nil {
   362  		t.idleConn = make(map[connectMethodKey][]*persistConn)
   363  	}
   364  	if len(t.idleConn[key]) >= max {
   365  		t.idleMu.Unlock()
   366  		pconn.close()
   367  		return false
   368  	}
   369  	for _, exist := range t.idleConn[key] {
   370  		if exist == pconn {
   371  			log.Fatalf("dup idle pconn %p in freelist", pconn)
   372  		}
   373  	}
   374  	t.idleConn[key] = append(t.idleConn[key], pconn)
   375  	t.idleMu.Unlock()
   376  	return true
   377  }
   378  
   379  // getIdleConnCh returns a channel to receive and return idle
   380  // persistent connection for the given connectMethod.
   381  // It may return nil, if persistent connections are not being used.
   382  func (t *Transport) getIdleConnCh(cm connectMethod) chan *persistConn {
   383  	if t.DisableKeepAlives {
   384  		return nil
   385  	}
   386  	key := cm.key()
   387  	t.idleMu.Lock()
   388  	defer t.idleMu.Unlock()
   389  	if t.idleConnCh == nil {
   390  		t.idleConnCh = make(map[connectMethodKey]chan *persistConn)
   391  	}
   392  	ch, ok := t.idleConnCh[key]
   393  	if !ok {
   394  		ch = make(chan *persistConn)
   395  		t.idleConnCh[key] = ch
   396  	}
   397  	return ch
   398  }
   399  
   400  func (t *Transport) getIdleConn(cm connectMethod) (pconn *persistConn) {
   401  	key := cm.key()
   402  	t.idleMu.Lock()
   403  	defer t.idleMu.Unlock()
   404  	if t.idleConn == nil {
   405  		return nil
   406  	}
   407  	for {
   408  		pconns, ok := t.idleConn[key]
   409  		if !ok {
   410  			return nil
   411  		}
   412  		if len(pconns) == 1 {
   413  			pconn = pconns[0]
   414  			delete(t.idleConn, key)
   415  		} else {
   416  			// 2 or more cached connections; pop last
   417  			// TODO: queue?
   418  			pconn = pconns[len(pconns)-1]
   419  			t.idleConn[key] = pconns[:len(pconns)-1]
   420  		}
   421  		if !pconn.isBroken() {
   422  			return
   423  		}
   424  	}
   425  }
   426  
   427  func (t *Transport) setReqCanceler(r *Request, fn func()) {
   428  	t.reqMu.Lock()
   429  	defer t.reqMu.Unlock()
   430  	if t.reqCanceler == nil {
   431  		t.reqCanceler = make(map[*Request]func())
   432  	}
   433  	if fn != nil {
   434  		t.reqCanceler[r] = fn
   435  	} else {
   436  		delete(t.reqCanceler, r)
   437  	}
   438  }
   439  
   440  func (t *Transport) dial(network, addr string) (c net.Conn, err error) {
   441  	if t.Dial != nil {
   442  		return t.Dial(network, addr)
   443  	}
   444  	return net.Dial(network, addr)
   445  }
   446  
   447  // getConn dials and creates a new persistConn to the target as
   448  // specified in the connectMethod.  This includes doing a proxy CONNECT
   449  // and/or setting up TLS.  If this doesn't return an error, the persistConn
   450  // is ready to write requests to.
   451  func (t *Transport) getConn(req *Request, cm connectMethod) (*persistConn, error) {
   452  	if pc := t.getIdleConn(cm); pc != nil {
   453  		return pc, nil
   454  	}
   455  
   456  	type dialRes struct {
   457  		pc  *persistConn
   458  		err error
   459  	}
   460  	dialc := make(chan dialRes)
   461  
   462  	handlePendingDial := func() {
   463  		if v := <-dialc; v.err == nil {
   464  			t.putIdleConn(v.pc)
   465  		}
   466  	}
   467  
   468  	cancelc := make(chan struct{})
   469  	t.setReqCanceler(req, func() { close(cancelc) })
   470  
   471  	go func() {
   472  		pc, err := t.dialConn(cm)
   473  		dialc <- dialRes{pc, err}
   474  	}()
   475  
   476  	idleConnCh := t.getIdleConnCh(cm)
   477  	select {
   478  	case v := <-dialc:
   479  		// Our dial finished.
   480  		return v.pc, v.err
   481  	case pc := <-idleConnCh:
   482  		// Another request finished first and its net.Conn
   483  		// became available before our dial. Or somebody
   484  		// else's dial that they didn't use.
   485  		// But our dial is still going, so give it away
   486  		// when it finishes:
   487  		go handlePendingDial()
   488  		return pc, nil
   489  	case <-cancelc:
   490  		go handlePendingDial()
   491  		return nil, errors.New("net/http: request canceled while waiting for connection")
   492  	}
   493  }
   494  
   495  func (t *Transport) dialConn(cm connectMethod) (*persistConn, error) {
   496  	conn, err := t.dial("tcp", cm.addr())
   497  	if err != nil {
   498  		if cm.proxyURL != nil {
   499  			err = fmt.Errorf("http: error connecting to proxy %s: %v", cm.proxyURL, err)
   500  		}
   501  		return nil, err
   502  	}
   503  
   504  	pa := cm.proxyAuth()
   505  
   506  	pconn := &persistConn{
   507  		t:          t,
   508  		cacheKey:   cm.key(),
   509  		conn:       conn,
   510  		reqch:      make(chan requestAndChan, 1),
   511  		writech:    make(chan writeRequest, 1),
   512  		closech:    make(chan struct{}),
   513  		writeErrCh: make(chan error, 1),
   514  	}
   515  
   516  	switch {
   517  	case cm.proxyURL == nil:
   518  		// Do nothing.
   519  	case cm.targetScheme == "http":
   520  		pconn.isProxy = true
   521  		if pa != "" {
   522  			pconn.mutateHeaderFunc = func(h Header) {
   523  				h.Set("Proxy-Authorization", pa)
   524  			}
   525  		}
   526  	case cm.targetScheme == "https":
   527  		connectReq := &Request{
   528  			Method: "CONNECT",
   529  			URL:    &url.URL{Opaque: cm.targetAddr},
   530  			Host:   cm.targetAddr,
   531  			Header: make(Header),
   532  		}
   533  		if pa != "" {
   534  			connectReq.Header.Set("Proxy-Authorization", pa)
   535  		}
   536  		connectReq.Write(conn)
   537  
   538  		// Read response.
   539  		// Okay to use and discard buffered reader here, because
   540  		// TLS server will not speak until spoken to.
   541  		br := bufio.NewReader(conn)
   542  		resp, err := ReadResponse(br, connectReq)
   543  		if err != nil {
   544  			conn.Close()
   545  			return nil, err
   546  		}
   547  		if resp.StatusCode != 200 {
   548  			f := strings.SplitN(resp.Status, " ", 2)
   549  			conn.Close()
   550  			return nil, errors.New(f[1])
   551  		}
   552  	}
   553  
   554  	if cm.targetScheme == "https" {
   555  		// Initiate TLS and check remote host name against certificate.
   556  		cfg := t.TLSClientConfig
   557  		if cfg == nil || cfg.ServerName == "" {
   558  			host := cm.tlsHost()
   559  			if cfg == nil {
   560  				cfg = &tls.Config{ServerName: host}
   561  			} else {
   562  				clone := *cfg // shallow clone
   563  				clone.ServerName = host
   564  				cfg = &clone
   565  			}
   566  		}
   567  		plainConn := conn
   568  		tlsConn := tls.Client(plainConn, cfg)
   569  		errc := make(chan error, 2)
   570  		var timer *time.Timer // for canceling TLS handshake
   571  		if d := t.TLSHandshakeTimeout; d != 0 {
   572  			timer = time.AfterFunc(d, func() {
   573  				errc <- tlsHandshakeTimeoutError{}
   574  			})
   575  		}
   576  		go func() {
   577  			err := tlsConn.Handshake()
   578  			if timer != nil {
   579  				timer.Stop()
   580  			}
   581  			errc <- err
   582  		}()
   583  		if err := <-errc; err != nil {
   584  			plainConn.Close()
   585  			return nil, err
   586  		}
   587  		if !cfg.InsecureSkipVerify {
   588  			if err := tlsConn.VerifyHostname(cfg.ServerName); err != nil {
   589  				plainConn.Close()
   590  				return nil, err
   591  			}
   592  		}
   593  		cs := tlsConn.ConnectionState()
   594  		pconn.tlsState = &cs
   595  		pconn.conn = tlsConn
   596  	}
   597  
   598  	pconn.br = bufio.NewReader(noteEOFReader{pconn.conn, &pconn.sawEOF})
   599  	pconn.bw = bufio.NewWriter(pconn.conn)
   600  	go pconn.readLoop()
   601  	go pconn.writeLoop()
   602  	return pconn, nil
   603  }
   604  
   605  // useProxy returns true if requests to addr should use a proxy,
   606  // according to the NO_PROXY or no_proxy environment variable.
   607  // addr is always a canonicalAddr with a host and port.
   608  func useProxy(addr string) bool {
   609  	if len(addr) == 0 {
   610  		return true
   611  	}
   612  	host, _, err := net.SplitHostPort(addr)
   613  	if err != nil {
   614  		return false
   615  	}
   616  	if host == "localhost" {
   617  		return false
   618  	}
   619  	if ip := net.ParseIP(host); ip != nil {
   620  		if ip.IsLoopback() {
   621  			return false
   622  		}
   623  	}
   624  
   625  	no_proxy := noProxyEnv.Get()
   626  	if no_proxy == "*" {
   627  		return false
   628  	}
   629  
   630  	addr = strings.ToLower(strings.TrimSpace(addr))
   631  	if hasPort(addr) {
   632  		addr = addr[:strings.LastIndex(addr, ":")]
   633  	}
   634  
   635  	for _, p := range strings.Split(no_proxy, ",") {
   636  		p = strings.ToLower(strings.TrimSpace(p))
   637  		if len(p) == 0 {
   638  			continue
   639  		}
   640  		if hasPort(p) {
   641  			p = p[:strings.LastIndex(p, ":")]
   642  		}
   643  		if addr == p {
   644  			return false
   645  		}
   646  		if p[0] == '.' && (strings.HasSuffix(addr, p) || addr == p[1:]) {
   647  			// no_proxy ".foo.com" matches "bar.foo.com" or "foo.com"
   648  			return false
   649  		}
   650  		if p[0] != '.' && strings.HasSuffix(addr, p) && addr[len(addr)-len(p)-1] == '.' {
   651  			// no_proxy "foo.com" matches "bar.foo.com"
   652  			return false
   653  		}
   654  	}
   655  	return true
   656  }
   657  
   658  // connectMethod is the map key (in its String form) for keeping persistent
   659  // TCP connections alive for subsequent HTTP requests.
   660  //
   661  // A connect method may be of the following types:
   662  //
   663  // Cache key form                Description
   664  // -----------------             -------------------------
   665  // |http|foo.com                 http directly to server, no proxy
   666  // |https|foo.com                https directly to server, no proxy
   667  // http://proxy.com|https|foo.com  http to proxy, then CONNECT to foo.com
   668  // http://proxy.com|http           http to proxy, http to anywhere after that
   669  //
   670  // Note: no support to https to the proxy yet.
   671  //
   672  type connectMethod struct {
   673  	proxyURL     *url.URL // nil for no proxy, else full proxy URL
   674  	targetScheme string   // "http" or "https"
   675  	targetAddr   string   // Not used if proxy + http targetScheme (4th example in table)
   676  }
   677  
   678  func (cm *connectMethod) key() connectMethodKey {
   679  	proxyStr := ""
   680  	targetAddr := cm.targetAddr
   681  	if cm.proxyURL != nil {
   682  		proxyStr = cm.proxyURL.String()
   683  		if cm.targetScheme == "http" {
   684  			targetAddr = ""
   685  		}
   686  	}
   687  	return connectMethodKey{
   688  		proxy:  proxyStr,
   689  		scheme: cm.targetScheme,
   690  		addr:   targetAddr,
   691  	}
   692  }
   693  
   694  // addr returns the first hop "host:port" to which we need to TCP connect.
   695  func (cm *connectMethod) addr() string {
   696  	if cm.proxyURL != nil {
   697  		return canonicalAddr(cm.proxyURL)
   698  	}
   699  	return cm.targetAddr
   700  }
   701  
   702  // tlsHost returns the host name to match against the peer's
   703  // TLS certificate.
   704  func (cm *connectMethod) tlsHost() string {
   705  	h := cm.targetAddr
   706  	if hasPort(h) {
   707  		h = h[:strings.LastIndex(h, ":")]
   708  	}
   709  	return h
   710  }
   711  
   712  // connectMethodKey is the map key version of connectMethod, with a
   713  // stringified proxy URL (or the empty string) instead of a pointer to
   714  // a URL.
   715  type connectMethodKey struct {
   716  	proxy, scheme, addr string
   717  }
   718  
   719  func (k connectMethodKey) String() string {
   720  	// Only used by tests.
   721  	return fmt.Sprintf("%s|%s|%s", k.proxy, k.scheme, k.addr)
   722  }
   723  
   724  // persistConn wraps a connection, usually a persistent one
   725  // (but may be used for non-keep-alive requests as well)
   726  type persistConn struct {
   727  	t        *Transport
   728  	cacheKey connectMethodKey
   729  	conn     net.Conn
   730  	tlsState *tls.ConnectionState
   731  	br       *bufio.Reader       // from conn
   732  	sawEOF   bool                // whether we've seen EOF from conn; owned by readLoop
   733  	bw       *bufio.Writer       // to conn
   734  	reqch    chan requestAndChan // written by roundTrip; read by readLoop
   735  	writech  chan writeRequest   // written by roundTrip; read by writeLoop
   736  	closech  chan struct{}       // closed when conn closed
   737  	isProxy  bool
   738  	// writeErrCh passes the request write error (usually nil)
   739  	// from the writeLoop goroutine to the readLoop which passes
   740  	// it off to the res.Body reader, which then uses it to decide
   741  	// whether or not a connection can be reused. Issue 7569.
   742  	writeErrCh chan error
   743  
   744  	lk                   sync.Mutex // guards following fields
   745  	numExpectedResponses int
   746  	closed               bool // whether conn has been closed
   747  	broken               bool // an error has happened on this connection; marked broken so it's not reused.
   748  	// mutateHeaderFunc is an optional func to modify extra
   749  	// headers on each outbound request before it's written. (the
   750  	// original Request given to RoundTrip is not modified)
   751  	mutateHeaderFunc func(Header)
   752  }
   753  
   754  // isBroken reports whether this connection is in a known broken state.
   755  func (pc *persistConn) isBroken() bool {
   756  	pc.lk.Lock()
   757  	b := pc.broken
   758  	pc.lk.Unlock()
   759  	return b
   760  }
   761  
   762  func (pc *persistConn) cancelRequest() {
   763  	pc.conn.Close()
   764  }
   765  
   766  var remoteSideClosedFunc func(error) bool // or nil to use default
   767  
   768  func remoteSideClosed(err error) bool {
   769  	if err == io.EOF {
   770  		return true
   771  	}
   772  	if remoteSideClosedFunc != nil {
   773  		return remoteSideClosedFunc(err)
   774  	}
   775  	return false
   776  }
   777  
   778  func (pc *persistConn) readLoop() {
   779  	alive := true
   780  
   781  	for alive {
   782  		pb, err := pc.br.Peek(1)
   783  
   784  		pc.lk.Lock()
   785  		if pc.numExpectedResponses == 0 {
   786  			if !pc.closed {
   787  				pc.closeLocked()
   788  				if len(pb) > 0 {
   789  					log.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v",
   790  						string(pb), err)
   791  				}
   792  			}
   793  			pc.lk.Unlock()
   794  			return
   795  		}
   796  		pc.lk.Unlock()
   797  
   798  		rc := <-pc.reqch
   799  
   800  		var resp *Response
   801  		if err == nil {
   802  			resp, err = ReadResponse(pc.br, rc.req)
   803  			if err == nil && resp.StatusCode == 100 {
   804  				// Skip any 100-continue for now.
   805  				// TODO(bradfitz): if rc.req had "Expect: 100-continue",
   806  				// actually block the request body write and signal the
   807  				// writeLoop now to begin sending it. (Issue 2184) For now we
   808  				// eat it, since we're never expecting one.
   809  				resp, err = ReadResponse(pc.br, rc.req)
   810  			}
   811  		}
   812  
   813  		if resp != nil {
   814  			resp.TLS = pc.tlsState
   815  		}
   816  
   817  		hasBody := resp != nil && rc.req.Method != "HEAD" && resp.ContentLength != 0
   818  
   819  		if err != nil {
   820  			pc.close()
   821  		} else {
   822  			if rc.addedGzip && hasBody && resp.Header.Get("Content-Encoding") == "gzip" {
   823  				resp.Header.Del("Content-Encoding")
   824  				resp.Header.Del("Content-Length")
   825  				resp.ContentLength = -1
   826  				resp.Body = &gzipReader{body: resp.Body}
   827  			}
   828  			resp.Body = &bodyEOFSignal{body: resp.Body}
   829  		}
   830  
   831  		if err != nil || resp.Close || rc.req.Close || resp.StatusCode <= 199 {
   832  			// Don't do keep-alive on error if either party requested a close
   833  			// or we get an unexpected informational (1xx) response.
   834  			// StatusCode 100 is already handled above.
   835  			alive = false
   836  		}
   837  
   838  		var waitForBodyRead chan bool
   839  		if hasBody {
   840  			waitForBodyRead = make(chan bool, 2)
   841  			resp.Body.(*bodyEOFSignal).earlyCloseFn = func() error {
   842  				// Sending false here sets alive to
   843  				// false and closes the connection
   844  				// below.
   845  				waitForBodyRead <- false
   846  				return nil
   847  			}
   848  			resp.Body.(*bodyEOFSignal).fn = func(err error) {
   849  				waitForBodyRead <- alive &&
   850  					err == nil &&
   851  					!pc.sawEOF &&
   852  					pc.wroteRequest() &&
   853  					pc.t.putIdleConn(pc)
   854  			}
   855  		}
   856  
   857  		if alive && !hasBody {
   858  			alive = !pc.sawEOF &&
   859  				pc.wroteRequest() &&
   860  				pc.t.putIdleConn(pc)
   861  		}
   862  
   863  		rc.ch <- responseAndError{resp, err}
   864  
   865  		// Wait for the just-returned response body to be fully consumed
   866  		// before we race and peek on the underlying bufio reader.
   867  		if waitForBodyRead != nil {
   868  			select {
   869  			case alive = <-waitForBodyRead:
   870  			case <-pc.closech:
   871  				alive = false
   872  			}
   873  		}
   874  
   875  		pc.t.setReqCanceler(rc.req, nil)
   876  
   877  		if !alive {
   878  			pc.close()
   879  		}
   880  	}
   881  }
   882  
   883  func (pc *persistConn) writeLoop() {
   884  	for {
   885  		select {
   886  		case wr := <-pc.writech:
   887  			if pc.isBroken() {
   888  				wr.ch <- errors.New("http: can't write HTTP request on broken connection")
   889  				continue
   890  			}
   891  			err := wr.req.Request.write(pc.bw, pc.isProxy, wr.req.extra)
   892  			if err == nil {
   893  				err = pc.bw.Flush()
   894  			}
   895  			if err != nil {
   896  				pc.markBroken()
   897  				wr.req.Request.closeBody()
   898  			}
   899  			pc.writeErrCh <- err // to the body reader, which might recycle us
   900  			wr.ch <- err         // to the roundTrip function
   901  		case <-pc.closech:
   902  			return
   903  		}
   904  	}
   905  }
   906  
   907  // wroteRequest is a check before recycling a connection that the previous write
   908  // (from writeLoop above) happened and was successful.
   909  func (pc *persistConn) wroteRequest() bool {
   910  	select {
   911  	case err := <-pc.writeErrCh:
   912  		// Common case: the write happened well before the response, so
   913  		// avoid creating a timer.
   914  		return err == nil
   915  	default:
   916  		// Rare case: the request was written in writeLoop above but
   917  		// before it could send to pc.writeErrCh, the reader read it
   918  		// all, processed it, and called us here. In this case, give the
   919  		// write goroutine a bit of time to finish its send.
   920  		//
   921  		// Less rare case: We also get here in the legitimate case of
   922  		// Issue 7569, where the writer is still writing (or stalled),
   923  		// but the server has already replied. In this case, we don't
   924  		// want to wait too long, and we want to return false so this
   925  		// connection isn't re-used.
   926  		select {
   927  		case err := <-pc.writeErrCh:
   928  			return err == nil
   929  		case <-time.After(50 * time.Millisecond):
   930  			return false
   931  		}
   932  	}
   933  }
   934  
   935  type responseAndError struct {
   936  	res *Response
   937  	err error
   938  }
   939  
   940  type requestAndChan struct {
   941  	req *Request
   942  	ch  chan responseAndError
   943  
   944  	// did the Transport (as opposed to the client code) add an
   945  	// Accept-Encoding gzip header? only if it we set it do
   946  	// we transparently decode the gzip.
   947  	addedGzip bool
   948  }
   949  
   950  // A writeRequest is sent by the readLoop's goroutine to the
   951  // writeLoop's goroutine to write a request while the read loop
   952  // concurrently waits on both the write response and the server's
   953  // reply.
   954  type writeRequest struct {
   955  	req *transportRequest
   956  	ch  chan<- error
   957  }
   958  
   959  type httpError struct {
   960  	err     string
   961  	timeout bool
   962  }
   963  
   964  func (e *httpError) Error() string   { return e.err }
   965  func (e *httpError) Timeout() bool   { return e.timeout }
   966  func (e *httpError) Temporary() bool { return true }
   967  
   968  var errTimeout error = &httpError{err: "net/http: timeout awaiting response headers", timeout: true}
   969  var errClosed error = &httpError{err: "net/http: transport closed before response was received"}
   970  
   971  func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err error) {
   972  	pc.t.setReqCanceler(req.Request, pc.cancelRequest)
   973  	pc.lk.Lock()
   974  	pc.numExpectedResponses++
   975  	headerFn := pc.mutateHeaderFunc
   976  	pc.lk.Unlock()
   977  
   978  	if headerFn != nil {
   979  		headerFn(req.extraHeaders())
   980  	}
   981  
   982  	// Ask for a compressed version if the caller didn't set their
   983  	// own value for Accept-Encoding. We only attempted to
   984  	// uncompress the gzip stream if we were the layer that
   985  	// requested it.
   986  	requestedGzip := false
   987  	if !pc.t.DisableCompression && req.Header.Get("Accept-Encoding") == "" && req.Method != "HEAD" {
   988  		// Request gzip only, not deflate. Deflate is ambiguous and
   989  		// not as universally supported anyway.
   990  		// See: http://www.gzip.org/zlib/zlib_faq.html#faq38
   991  		//
   992  		// Note that we don't request this for HEAD requests,
   993  		// due to a bug in nginx:
   994  		//   http://trac.nginx.org/nginx/ticket/358
   995  		//   http://golang.org/issue/5522
   996  		requestedGzip = true
   997  		req.extraHeaders().Set("Accept-Encoding", "gzip")
   998  	}
   999  
  1000  	// Write the request concurrently with waiting for a response,
  1001  	// in case the server decides to reply before reading our full
  1002  	// request body.
  1003  	writeErrCh := make(chan error, 1)
  1004  	pc.writech <- writeRequest{req, writeErrCh}
  1005  
  1006  	resc := make(chan responseAndError, 1)
  1007  	pc.reqch <- requestAndChan{req.Request, resc, requestedGzip}
  1008  
  1009  	var re responseAndError
  1010  	var pconnDeadCh = pc.closech
  1011  	var failTicker <-chan time.Time
  1012  	var respHeaderTimer <-chan time.Time
  1013  WaitResponse:
  1014  	for {
  1015  		select {
  1016  		case err := <-writeErrCh:
  1017  			if err != nil {
  1018  				re = responseAndError{nil, err}
  1019  				pc.close()
  1020  				break WaitResponse
  1021  			}
  1022  			if d := pc.t.ResponseHeaderTimeout; d > 0 {
  1023  				respHeaderTimer = time.After(d)
  1024  			}
  1025  		case <-pconnDeadCh:
  1026  			// The persist connection is dead. This shouldn't
  1027  			// usually happen (only with Connection: close responses
  1028  			// with no response bodies), but if it does happen it
  1029  			// means either a) the remote server hung up on us
  1030  			// prematurely, or b) the readLoop sent us a response &
  1031  			// closed its closech at roughly the same time, and we
  1032  			// selected this case first, in which case a response
  1033  			// might still be coming soon.
  1034  			//
  1035  			// We can't avoid the select race in b) by using a unbuffered
  1036  			// resc channel instead, because then goroutines can
  1037  			// leak if we exit due to other errors.
  1038  			pconnDeadCh = nil                               // avoid spinning
  1039  			failTicker = time.After(100 * time.Millisecond) // arbitrary time to wait for resc
  1040  		case <-failTicker:
  1041  			re = responseAndError{err: errClosed}
  1042  			break WaitResponse
  1043  		case <-respHeaderTimer:
  1044  			pc.close()
  1045  			re = responseAndError{err: errTimeout}
  1046  			break WaitResponse
  1047  		case re = <-resc:
  1048  			break WaitResponse
  1049  		}
  1050  	}
  1051  
  1052  	pc.lk.Lock()
  1053  	pc.numExpectedResponses--
  1054  	pc.lk.Unlock()
  1055  
  1056  	if re.err != nil {
  1057  		pc.t.setReqCanceler(req.Request, nil)
  1058  	}
  1059  	return re.res, re.err
  1060  }
  1061  
  1062  // markBroken marks a connection as broken (so it's not reused).
  1063  // It differs from close in that it doesn't close the underlying
  1064  // connection for use when it's still being read.
  1065  func (pc *persistConn) markBroken() {
  1066  	pc.lk.Lock()
  1067  	defer pc.lk.Unlock()
  1068  	pc.broken = true
  1069  }
  1070  
  1071  func (pc *persistConn) close() {
  1072  	pc.lk.Lock()
  1073  	defer pc.lk.Unlock()
  1074  	pc.closeLocked()
  1075  }
  1076  
  1077  func (pc *persistConn) closeLocked() {
  1078  	pc.broken = true
  1079  	if !pc.closed {
  1080  		pc.conn.Close()
  1081  		pc.closed = true
  1082  		close(pc.closech)
  1083  	}
  1084  	pc.mutateHeaderFunc = nil
  1085  }
  1086  
  1087  var portMap = map[string]string{
  1088  	"http":  "80",
  1089  	"https": "443",
  1090  }
  1091  
  1092  // canonicalAddr returns url.Host but always with a ":port" suffix
  1093  func canonicalAddr(url *url.URL) string {
  1094  	addr := url.Host
  1095  	if !hasPort(addr) {
  1096  		return addr + ":" + portMap[url.Scheme]
  1097  	}
  1098  	return addr
  1099  }
  1100  
  1101  // bodyEOFSignal wraps a ReadCloser but runs fn (if non-nil) at most
  1102  // once, right before its final (error-producing) Read or Close call
  1103  // returns. If earlyCloseFn is non-nil and Close is called before
  1104  // io.EOF is seen, earlyCloseFn is called instead of fn, and its
  1105  // return value is the return value from Close.
  1106  type bodyEOFSignal struct {
  1107  	body         io.ReadCloser
  1108  	mu           sync.Mutex   // guards following 4 fields
  1109  	closed       bool         // whether Close has been called
  1110  	rerr         error        // sticky Read error
  1111  	fn           func(error)  // error will be nil on Read io.EOF
  1112  	earlyCloseFn func() error // optional alt Close func used if io.EOF not seen
  1113  }
  1114  
  1115  func (es *bodyEOFSignal) Read(p []byte) (n int, err error) {
  1116  	es.mu.Lock()
  1117  	closed, rerr := es.closed, es.rerr
  1118  	es.mu.Unlock()
  1119  	if closed {
  1120  		return 0, errors.New("http: read on closed response body")
  1121  	}
  1122  	if rerr != nil {
  1123  		return 0, rerr
  1124  	}
  1125  
  1126  	n, err = es.body.Read(p)
  1127  	if err != nil {
  1128  		es.mu.Lock()
  1129  		defer es.mu.Unlock()
  1130  		if es.rerr == nil {
  1131  			es.rerr = err
  1132  		}
  1133  		es.condfn(err)
  1134  	}
  1135  	return
  1136  }
  1137  
  1138  func (es *bodyEOFSignal) Close() error {
  1139  	es.mu.Lock()
  1140  	defer es.mu.Unlock()
  1141  	if es.closed {
  1142  		return nil
  1143  	}
  1144  	es.closed = true
  1145  	if es.earlyCloseFn != nil && es.rerr != io.EOF {
  1146  		return es.earlyCloseFn()
  1147  	}
  1148  	err := es.body.Close()
  1149  	es.condfn(err)
  1150  	return err
  1151  }
  1152  
  1153  // caller must hold es.mu.
  1154  func (es *bodyEOFSignal) condfn(err error) {
  1155  	if es.fn == nil {
  1156  		return
  1157  	}
  1158  	if err == io.EOF {
  1159  		err = nil
  1160  	}
  1161  	es.fn(err)
  1162  	es.fn = nil
  1163  }
  1164  
  1165  // gzipReader wraps a response body so it can lazily
  1166  // call gzip.NewReader on the first call to Read
  1167  type gzipReader struct {
  1168  	body io.ReadCloser // underlying Response.Body
  1169  	zr   io.Reader     // lazily-initialized gzip reader
  1170  }
  1171  
  1172  func (gz *gzipReader) Read(p []byte) (n int, err error) {
  1173  	if gz.zr == nil {
  1174  		gz.zr, err = gzip.NewReader(gz.body)
  1175  		if err != nil {
  1176  			return 0, err
  1177  		}
  1178  	}
  1179  	return gz.zr.Read(p)
  1180  }
  1181  
  1182  func (gz *gzipReader) Close() error {
  1183  	return gz.body.Close()
  1184  }
  1185  
  1186  type readerAndCloser struct {
  1187  	io.Reader
  1188  	io.Closer
  1189  }
  1190  
  1191  type tlsHandshakeTimeoutError struct{}
  1192  
  1193  func (tlsHandshakeTimeoutError) Timeout() bool   { return true }
  1194  func (tlsHandshakeTimeoutError) Temporary() bool { return true }
  1195  func (tlsHandshakeTimeoutError) Error() string   { return "net/http: TLS handshake timeout" }
  1196  
  1197  type noteEOFReader struct {
  1198  	r      io.Reader
  1199  	sawEOF *bool
  1200  }
  1201  
  1202  func (nr noteEOFReader) Read(p []byte) (n int, err error) {
  1203  	n, err = nr.r.Read(p)
  1204  	if err == io.EOF {
  1205  		*nr.sawEOF = true
  1206  	}
  1207  	return
  1208  }