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