github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/net/http/transport_test.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  // Tests for transport.go
     6  
     7  package http_test
     8  
     9  import (
    10  	"bufio"
    11  	"bytes"
    12  	"compress/gzip"
    13  	"crypto/rand"
    14  	"fmt"
    15  	"io"
    16  	"io/ioutil"
    17  	"net"
    18  	"net/http"
    19  	. "net/http"
    20  	"net/http/httptest"
    21  	"net/url"
    22  	"os"
    23  	"runtime"
    24  	"strconv"
    25  	"strings"
    26  	"sync"
    27  	"testing"
    28  	"time"
    29  )
    30  
    31  // TODO: test 5 pipelined requests with responses: 1) OK, 2) OK, Connection: Close
    32  //       and then verify that the final 2 responses get errors back.
    33  
    34  // hostPortHandler writes back the client's "host:port".
    35  var hostPortHandler = HandlerFunc(func(w ResponseWriter, r *Request) {
    36  	if r.FormValue("close") == "true" {
    37  		w.Header().Set("Connection", "close")
    38  	}
    39  	w.Write([]byte(r.RemoteAddr))
    40  })
    41  
    42  // testCloseConn is a net.Conn tracked by a testConnSet.
    43  type testCloseConn struct {
    44  	net.Conn
    45  	set *testConnSet
    46  }
    47  
    48  func (c *testCloseConn) Close() error {
    49  	c.set.remove(c)
    50  	return c.Conn.Close()
    51  }
    52  
    53  // testConnSet tracks a set of TCP connections and whether they've
    54  // been closed.
    55  type testConnSet struct {
    56  	t      *testing.T
    57  	closed map[net.Conn]bool
    58  	list   []net.Conn // in order created
    59  	mutex  sync.Mutex
    60  }
    61  
    62  func (tcs *testConnSet) insert(c net.Conn) {
    63  	tcs.mutex.Lock()
    64  	defer tcs.mutex.Unlock()
    65  	tcs.closed[c] = false
    66  	tcs.list = append(tcs.list, c)
    67  }
    68  
    69  func (tcs *testConnSet) remove(c net.Conn) {
    70  	tcs.mutex.Lock()
    71  	defer tcs.mutex.Unlock()
    72  	tcs.closed[c] = true
    73  }
    74  
    75  // some tests use this to manage raw tcp connections for later inspection
    76  func makeTestDial(t *testing.T) (*testConnSet, func(n, addr string) (net.Conn, error)) {
    77  	connSet := &testConnSet{
    78  		t:      t,
    79  		closed: make(map[net.Conn]bool),
    80  	}
    81  	dial := func(n, addr string) (net.Conn, error) {
    82  		c, err := net.Dial(n, addr)
    83  		if err != nil {
    84  			return nil, err
    85  		}
    86  		tc := &testCloseConn{c, connSet}
    87  		connSet.insert(tc)
    88  		return tc, nil
    89  	}
    90  	return connSet, dial
    91  }
    92  
    93  func (tcs *testConnSet) check(t *testing.T) {
    94  	tcs.mutex.Lock()
    95  	defer tcs.mutex.Unlock()
    96  
    97  	for i, c := range tcs.list {
    98  		if !tcs.closed[c] {
    99  			t.Errorf("TCP connection #%d, %p (of %d total) was not closed", i+1, c, len(tcs.list))
   100  		}
   101  	}
   102  }
   103  
   104  // Two subsequent requests and verify their response is the same.
   105  // The response from the server is our own IP:port
   106  func TestTransportKeepAlives(t *testing.T) {
   107  	defer afterTest(t)
   108  	ts := httptest.NewServer(hostPortHandler)
   109  	defer ts.Close()
   110  
   111  	for _, disableKeepAlive := range []bool{false, true} {
   112  		tr := &Transport{DisableKeepAlives: disableKeepAlive}
   113  		defer tr.CloseIdleConnections()
   114  		c := &Client{Transport: tr}
   115  
   116  		fetch := func(n int) string {
   117  			res, err := c.Get(ts.URL)
   118  			if err != nil {
   119  				t.Fatalf("error in disableKeepAlive=%v, req #%d, GET: %v", disableKeepAlive, n, err)
   120  			}
   121  			body, err := ioutil.ReadAll(res.Body)
   122  			if err != nil {
   123  				t.Fatalf("error in disableKeepAlive=%v, req #%d, ReadAll: %v", disableKeepAlive, n, err)
   124  			}
   125  			return string(body)
   126  		}
   127  
   128  		body1 := fetch(1)
   129  		body2 := fetch(2)
   130  
   131  		bodiesDiffer := body1 != body2
   132  		if bodiesDiffer != disableKeepAlive {
   133  			t.Errorf("error in disableKeepAlive=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
   134  				disableKeepAlive, bodiesDiffer, body1, body2)
   135  		}
   136  	}
   137  }
   138  
   139  func TestTransportConnectionCloseOnResponse(t *testing.T) {
   140  	defer afterTest(t)
   141  	ts := httptest.NewServer(hostPortHandler)
   142  	defer ts.Close()
   143  
   144  	connSet, testDial := makeTestDial(t)
   145  
   146  	for _, connectionClose := range []bool{false, true} {
   147  		tr := &Transport{
   148  			Dial: testDial,
   149  		}
   150  		c := &Client{Transport: tr}
   151  
   152  		fetch := func(n int) string {
   153  			req := new(Request)
   154  			var err error
   155  			req.URL, err = url.Parse(ts.URL + fmt.Sprintf("/?close=%v", connectionClose))
   156  			if err != nil {
   157  				t.Fatalf("URL parse error: %v", err)
   158  			}
   159  			req.Method = "GET"
   160  			req.Proto = "HTTP/1.1"
   161  			req.ProtoMajor = 1
   162  			req.ProtoMinor = 1
   163  
   164  			res, err := c.Do(req)
   165  			if err != nil {
   166  				t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err)
   167  			}
   168  			defer res.Body.Close()
   169  			body, err := ioutil.ReadAll(res.Body)
   170  			if err != nil {
   171  				t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err)
   172  			}
   173  			return string(body)
   174  		}
   175  
   176  		body1 := fetch(1)
   177  		body2 := fetch(2)
   178  		bodiesDiffer := body1 != body2
   179  		if bodiesDiffer != connectionClose {
   180  			t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
   181  				connectionClose, bodiesDiffer, body1, body2)
   182  		}
   183  
   184  		tr.CloseIdleConnections()
   185  	}
   186  
   187  	connSet.check(t)
   188  }
   189  
   190  func TestTransportConnectionCloseOnRequest(t *testing.T) {
   191  	defer afterTest(t)
   192  	ts := httptest.NewServer(hostPortHandler)
   193  	defer ts.Close()
   194  
   195  	connSet, testDial := makeTestDial(t)
   196  
   197  	for _, connectionClose := range []bool{false, true} {
   198  		tr := &Transport{
   199  			Dial: testDial,
   200  		}
   201  		c := &Client{Transport: tr}
   202  
   203  		fetch := func(n int) string {
   204  			req := new(Request)
   205  			var err error
   206  			req.URL, err = url.Parse(ts.URL)
   207  			if err != nil {
   208  				t.Fatalf("URL parse error: %v", err)
   209  			}
   210  			req.Method = "GET"
   211  			req.Proto = "HTTP/1.1"
   212  			req.ProtoMajor = 1
   213  			req.ProtoMinor = 1
   214  			req.Close = connectionClose
   215  
   216  			res, err := c.Do(req)
   217  			if err != nil {
   218  				t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err)
   219  			}
   220  			body, err := ioutil.ReadAll(res.Body)
   221  			if err != nil {
   222  				t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err)
   223  			}
   224  			return string(body)
   225  		}
   226  
   227  		body1 := fetch(1)
   228  		body2 := fetch(2)
   229  		bodiesDiffer := body1 != body2
   230  		if bodiesDiffer != connectionClose {
   231  			t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
   232  				connectionClose, bodiesDiffer, body1, body2)
   233  		}
   234  
   235  		tr.CloseIdleConnections()
   236  	}
   237  
   238  	connSet.check(t)
   239  }
   240  
   241  func TestTransportIdleCacheKeys(t *testing.T) {
   242  	defer afterTest(t)
   243  	ts := httptest.NewServer(hostPortHandler)
   244  	defer ts.Close()
   245  
   246  	tr := &Transport{DisableKeepAlives: false}
   247  	c := &Client{Transport: tr}
   248  
   249  	if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g {
   250  		t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g)
   251  	}
   252  
   253  	resp, err := c.Get(ts.URL)
   254  	if err != nil {
   255  		t.Error(err)
   256  	}
   257  	ioutil.ReadAll(resp.Body)
   258  
   259  	keys := tr.IdleConnKeysForTesting()
   260  	if e, g := 1, len(keys); e != g {
   261  		t.Fatalf("After Get expected %d idle conn cache keys; got %d", e, g)
   262  	}
   263  
   264  	if e := "|http|" + ts.Listener.Addr().String(); keys[0] != e {
   265  		t.Errorf("Expected idle cache key %q; got %q", e, keys[0])
   266  	}
   267  
   268  	tr.CloseIdleConnections()
   269  	if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g {
   270  		t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g)
   271  	}
   272  }
   273  
   274  func TestTransportMaxPerHostIdleConns(t *testing.T) {
   275  	defer afterTest(t)
   276  	resch := make(chan string)
   277  	gotReq := make(chan bool)
   278  	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
   279  		gotReq <- true
   280  		msg := <-resch
   281  		_, err := w.Write([]byte(msg))
   282  		if err != nil {
   283  			t.Fatalf("Write: %v", err)
   284  		}
   285  	}))
   286  	defer ts.Close()
   287  	maxIdleConns := 2
   288  	tr := &Transport{DisableKeepAlives: false, MaxIdleConnsPerHost: maxIdleConns}
   289  	c := &Client{Transport: tr}
   290  
   291  	// Start 3 outstanding requests and wait for the server to get them.
   292  	// Their responses will hang until we write to resch, though.
   293  	donech := make(chan bool)
   294  	doReq := func() {
   295  		resp, err := c.Get(ts.URL)
   296  		if err != nil {
   297  			t.Error(err)
   298  		}
   299  		_, err = ioutil.ReadAll(resp.Body)
   300  		if err != nil {
   301  			t.Fatalf("ReadAll: %v", err)
   302  		}
   303  		donech <- true
   304  	}
   305  	go doReq()
   306  	<-gotReq
   307  	go doReq()
   308  	<-gotReq
   309  	go doReq()
   310  	<-gotReq
   311  
   312  	if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g {
   313  		t.Fatalf("Before writes, expected %d idle conn cache keys; got %d", e, g)
   314  	}
   315  
   316  	resch <- "res1"
   317  	<-donech
   318  	keys := tr.IdleConnKeysForTesting()
   319  	if e, g := 1, len(keys); e != g {
   320  		t.Fatalf("after first response, expected %d idle conn cache keys; got %d", e, g)
   321  	}
   322  	cacheKey := "|http|" + ts.Listener.Addr().String()
   323  	if keys[0] != cacheKey {
   324  		t.Fatalf("Expected idle cache key %q; got %q", cacheKey, keys[0])
   325  	}
   326  	if e, g := 1, tr.IdleConnCountForTesting(cacheKey); e != g {
   327  		t.Errorf("after first response, expected %d idle conns; got %d", e, g)
   328  	}
   329  
   330  	resch <- "res2"
   331  	<-donech
   332  	if e, g := 2, tr.IdleConnCountForTesting(cacheKey); e != g {
   333  		t.Errorf("after second response, expected %d idle conns; got %d", e, g)
   334  	}
   335  
   336  	resch <- "res3"
   337  	<-donech
   338  	if e, g := maxIdleConns, tr.IdleConnCountForTesting(cacheKey); e != g {
   339  		t.Errorf("after third response, still expected %d idle conns; got %d", e, g)
   340  	}
   341  }
   342  
   343  func TestTransportServerClosingUnexpectedly(t *testing.T) {
   344  	defer afterTest(t)
   345  	ts := httptest.NewServer(hostPortHandler)
   346  	defer ts.Close()
   347  
   348  	tr := &Transport{}
   349  	c := &Client{Transport: tr}
   350  
   351  	fetch := func(n, retries int) string {
   352  		condFatalf := func(format string, arg ...interface{}) {
   353  			if retries <= 0 {
   354  				t.Fatalf(format, arg...)
   355  			}
   356  			t.Logf("retrying shortly after expected error: "+format, arg...)
   357  			time.Sleep(time.Second / time.Duration(retries))
   358  		}
   359  		for retries >= 0 {
   360  			retries--
   361  			res, err := c.Get(ts.URL)
   362  			if err != nil {
   363  				condFatalf("error in req #%d, GET: %v", n, err)
   364  				continue
   365  			}
   366  			body, err := ioutil.ReadAll(res.Body)
   367  			if err != nil {
   368  				condFatalf("error in req #%d, ReadAll: %v", n, err)
   369  				continue
   370  			}
   371  			res.Body.Close()
   372  			return string(body)
   373  		}
   374  		panic("unreachable")
   375  	}
   376  
   377  	body1 := fetch(1, 0)
   378  	body2 := fetch(2, 0)
   379  
   380  	ts.CloseClientConnections() // surprise!
   381  
   382  	// This test has an expected race. Sleeping for 25 ms prevents
   383  	// it on most fast machines, causing the next fetch() call to
   384  	// succeed quickly.  But if we do get errors, fetch() will retry 5
   385  	// times with some delays between.
   386  	time.Sleep(25 * time.Millisecond)
   387  
   388  	body3 := fetch(3, 5)
   389  
   390  	if body1 != body2 {
   391  		t.Errorf("expected body1 and body2 to be equal")
   392  	}
   393  	if body2 == body3 {
   394  		t.Errorf("expected body2 and body3 to be different")
   395  	}
   396  }
   397  
   398  // Test for http://golang.org/issue/2616 (appropriate issue number)
   399  // This fails pretty reliably with GOMAXPROCS=100 or something high.
   400  func TestStressSurpriseServerCloses(t *testing.T) {
   401  	defer afterTest(t)
   402  	if testing.Short() {
   403  		t.Skip("skipping test in short mode")
   404  	}
   405  	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
   406  		w.Header().Set("Content-Length", "5")
   407  		w.Header().Set("Content-Type", "text/plain")
   408  		w.Write([]byte("Hello"))
   409  		w.(Flusher).Flush()
   410  		conn, buf, _ := w.(Hijacker).Hijack()
   411  		buf.Flush()
   412  		conn.Close()
   413  	}))
   414  	defer ts.Close()
   415  
   416  	tr := &Transport{DisableKeepAlives: false}
   417  	c := &Client{Transport: tr}
   418  
   419  	// Do a bunch of traffic from different goroutines. Send to activityc
   420  	// after each request completes, regardless of whether it failed.
   421  	const (
   422  		numClients    = 50
   423  		reqsPerClient = 250
   424  	)
   425  	activityc := make(chan bool)
   426  	for i := 0; i < numClients; i++ {
   427  		go func() {
   428  			for i := 0; i < reqsPerClient; i++ {
   429  				res, err := c.Get(ts.URL)
   430  				if err == nil {
   431  					// We expect errors since the server is
   432  					// hanging up on us after telling us to
   433  					// send more requests, so we don't
   434  					// actually care what the error is.
   435  					// But we want to close the body in cases
   436  					// where we won the race.
   437  					res.Body.Close()
   438  				}
   439  				activityc <- true
   440  			}
   441  		}()
   442  	}
   443  
   444  	// Make sure all the request come back, one way or another.
   445  	for i := 0; i < numClients*reqsPerClient; i++ {
   446  		select {
   447  		case <-activityc:
   448  		case <-time.After(5 * time.Second):
   449  			t.Fatalf("presumed deadlock; no HTTP client activity seen in awhile")
   450  		}
   451  	}
   452  }
   453  
   454  // TestTransportHeadResponses verifies that we deal with Content-Lengths
   455  // with no bodies properly
   456  func TestTransportHeadResponses(t *testing.T) {
   457  	defer afterTest(t)
   458  	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
   459  		if r.Method != "HEAD" {
   460  			panic("expected HEAD; got " + r.Method)
   461  		}
   462  		w.Header().Set("Content-Length", "123")
   463  		w.WriteHeader(200)
   464  	}))
   465  	defer ts.Close()
   466  
   467  	tr := &Transport{DisableKeepAlives: false}
   468  	c := &Client{Transport: tr}
   469  	for i := 0; i < 2; i++ {
   470  		res, err := c.Head(ts.URL)
   471  		if err != nil {
   472  			t.Errorf("error on loop %d: %v", i, err)
   473  			continue
   474  		}
   475  		if e, g := "123", res.Header.Get("Content-Length"); e != g {
   476  			t.Errorf("loop %d: expected Content-Length header of %q, got %q", i, e, g)
   477  		}
   478  		if e, g := int64(123), res.ContentLength; e != g {
   479  			t.Errorf("loop %d: expected res.ContentLength of %v, got %v", i, e, g)
   480  		}
   481  		if all, err := ioutil.ReadAll(res.Body); err != nil {
   482  			t.Errorf("loop %d: Body ReadAll: %v", i, err)
   483  		} else if len(all) != 0 {
   484  			t.Errorf("Bogus body %q", all)
   485  		}
   486  	}
   487  }
   488  
   489  // TestTransportHeadChunkedResponse verifies that we ignore chunked transfer-encoding
   490  // on responses to HEAD requests.
   491  func TestTransportHeadChunkedResponse(t *testing.T) {
   492  	defer afterTest(t)
   493  	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
   494  		if r.Method != "HEAD" {
   495  			panic("expected HEAD; got " + r.Method)
   496  		}
   497  		w.Header().Set("Transfer-Encoding", "chunked") // client should ignore
   498  		w.Header().Set("x-client-ipport", r.RemoteAddr)
   499  		w.WriteHeader(200)
   500  	}))
   501  	defer ts.Close()
   502  
   503  	tr := &Transport{DisableKeepAlives: false}
   504  	c := &Client{Transport: tr}
   505  
   506  	res1, err := c.Head(ts.URL)
   507  	if err != nil {
   508  		t.Fatalf("request 1 error: %v", err)
   509  	}
   510  	res2, err := c.Head(ts.URL)
   511  	if err != nil {
   512  		t.Fatalf("request 2 error: %v", err)
   513  	}
   514  	if v1, v2 := res1.Header.Get("x-client-ipport"), res2.Header.Get("x-client-ipport"); v1 != v2 {
   515  		t.Errorf("ip/ports differed between head requests: %q vs %q", v1, v2)
   516  	}
   517  }
   518  
   519  var roundTripTests = []struct {
   520  	accept       string
   521  	expectAccept string
   522  	compressed   bool
   523  }{
   524  	// Requests with no accept-encoding header use transparent compression
   525  	{"", "gzip", false},
   526  	// Requests with other accept-encoding should pass through unmodified
   527  	{"foo", "foo", false},
   528  	// Requests with accept-encoding == gzip should be passed through
   529  	{"gzip", "gzip", true},
   530  }
   531  
   532  // Test that the modification made to the Request by the RoundTripper is cleaned up
   533  func TestRoundTripGzip(t *testing.T) {
   534  	defer afterTest(t)
   535  	const responseBody = "test response body"
   536  	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
   537  		accept := req.Header.Get("Accept-Encoding")
   538  		if expect := req.FormValue("expect_accept"); accept != expect {
   539  			t.Errorf("in handler, test %v: Accept-Encoding = %q, want %q",
   540  				req.FormValue("testnum"), accept, expect)
   541  		}
   542  		if accept == "gzip" {
   543  			rw.Header().Set("Content-Encoding", "gzip")
   544  			gz := gzip.NewWriter(rw)
   545  			gz.Write([]byte(responseBody))
   546  			gz.Close()
   547  		} else {
   548  			rw.Header().Set("Content-Encoding", accept)
   549  			rw.Write([]byte(responseBody))
   550  		}
   551  	}))
   552  	defer ts.Close()
   553  
   554  	for i, test := range roundTripTests {
   555  		// Test basic request (no accept-encoding)
   556  		req, _ := NewRequest("GET", fmt.Sprintf("%s/?testnum=%d&expect_accept=%s", ts.URL, i, test.expectAccept), nil)
   557  		if test.accept != "" {
   558  			req.Header.Set("Accept-Encoding", test.accept)
   559  		}
   560  		res, err := DefaultTransport.RoundTrip(req)
   561  		var body []byte
   562  		if test.compressed {
   563  			var r *gzip.Reader
   564  			r, err = gzip.NewReader(res.Body)
   565  			if err != nil {
   566  				t.Errorf("%d. gzip NewReader: %v", i, err)
   567  				continue
   568  			}
   569  			body, err = ioutil.ReadAll(r)
   570  			res.Body.Close()
   571  		} else {
   572  			body, err = ioutil.ReadAll(res.Body)
   573  		}
   574  		if err != nil {
   575  			t.Errorf("%d. Error: %q", i, err)
   576  			continue
   577  		}
   578  		if g, e := string(body), responseBody; g != e {
   579  			t.Errorf("%d. body = %q; want %q", i, g, e)
   580  		}
   581  		if g, e := req.Header.Get("Accept-Encoding"), test.accept; g != e {
   582  			t.Errorf("%d. Accept-Encoding = %q; want %q (it was mutated, in violation of RoundTrip contract)", i, g, e)
   583  		}
   584  		if g, e := res.Header.Get("Content-Encoding"), test.accept; g != e {
   585  			t.Errorf("%d. Content-Encoding = %q; want %q", i, g, e)
   586  		}
   587  	}
   588  
   589  }
   590  
   591  func TestTransportGzip(t *testing.T) {
   592  	defer afterTest(t)
   593  	const testString = "The test string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
   594  	const nRandBytes = 1024 * 1024
   595  	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
   596  		if req.Method == "HEAD" {
   597  			if g := req.Header.Get("Accept-Encoding"); g != "" {
   598  				t.Errorf("HEAD request sent with Accept-Encoding of %q; want none", g)
   599  			}
   600  			return
   601  		}
   602  		if g, e := req.Header.Get("Accept-Encoding"), "gzip"; g != e {
   603  			t.Errorf("Accept-Encoding = %q, want %q", g, e)
   604  		}
   605  		rw.Header().Set("Content-Encoding", "gzip")
   606  
   607  		var w io.Writer = rw
   608  		var buf bytes.Buffer
   609  		if req.FormValue("chunked") == "0" {
   610  			w = &buf
   611  			defer io.Copy(rw, &buf)
   612  			defer func() {
   613  				rw.Header().Set("Content-Length", strconv.Itoa(buf.Len()))
   614  			}()
   615  		}
   616  		gz := gzip.NewWriter(w)
   617  		gz.Write([]byte(testString))
   618  		if req.FormValue("body") == "large" {
   619  			io.CopyN(gz, rand.Reader, nRandBytes)
   620  		}
   621  		gz.Close()
   622  	}))
   623  	defer ts.Close()
   624  
   625  	for _, chunked := range []string{"1", "0"} {
   626  		c := &Client{Transport: &Transport{}}
   627  
   628  		// First fetch something large, but only read some of it.
   629  		res, err := c.Get(ts.URL + "/?body=large&chunked=" + chunked)
   630  		if err != nil {
   631  			t.Fatalf("large get: %v", err)
   632  		}
   633  		buf := make([]byte, len(testString))
   634  		n, err := io.ReadFull(res.Body, buf)
   635  		if err != nil {
   636  			t.Fatalf("partial read of large response: size=%d, %v", n, err)
   637  		}
   638  		if e, g := testString, string(buf); e != g {
   639  			t.Errorf("partial read got %q, expected %q", g, e)
   640  		}
   641  		res.Body.Close()
   642  		// Read on the body, even though it's closed
   643  		n, err = res.Body.Read(buf)
   644  		if n != 0 || err == nil {
   645  			t.Errorf("expected error post-closed large Read; got = %d, %v", n, err)
   646  		}
   647  
   648  		// Then something small.
   649  		res, err = c.Get(ts.URL + "/?chunked=" + chunked)
   650  		if err != nil {
   651  			t.Fatal(err)
   652  		}
   653  		body, err := ioutil.ReadAll(res.Body)
   654  		if err != nil {
   655  			t.Fatal(err)
   656  		}
   657  		if g, e := string(body), testString; g != e {
   658  			t.Fatalf("body = %q; want %q", g, e)
   659  		}
   660  		if g, e := res.Header.Get("Content-Encoding"), ""; g != e {
   661  			t.Fatalf("Content-Encoding = %q; want %q", g, e)
   662  		}
   663  
   664  		// Read on the body after it's been fully read:
   665  		n, err = res.Body.Read(buf)
   666  		if n != 0 || err == nil {
   667  			t.Errorf("expected Read error after exhausted reads; got %d, %v", n, err)
   668  		}
   669  		res.Body.Close()
   670  		n, err = res.Body.Read(buf)
   671  		if n != 0 || err == nil {
   672  			t.Errorf("expected Read error after Close; got %d, %v", n, err)
   673  		}
   674  	}
   675  
   676  	// And a HEAD request too, because they're always weird.
   677  	c := &Client{Transport: &Transport{}}
   678  	res, err := c.Head(ts.URL)
   679  	if err != nil {
   680  		t.Fatalf("Head: %v", err)
   681  	}
   682  	if res.StatusCode != 200 {
   683  		t.Errorf("Head status=%d; want=200", res.StatusCode)
   684  	}
   685  }
   686  
   687  func TestTransportProxy(t *testing.T) {
   688  	defer afterTest(t)
   689  	ch := make(chan string, 1)
   690  	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
   691  		ch <- "real server"
   692  	}))
   693  	defer ts.Close()
   694  	proxy := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
   695  		ch <- "proxy for " + r.URL.String()
   696  	}))
   697  	defer proxy.Close()
   698  
   699  	pu, err := url.Parse(proxy.URL)
   700  	if err != nil {
   701  		t.Fatal(err)
   702  	}
   703  	c := &Client{Transport: &Transport{Proxy: ProxyURL(pu)}}
   704  	c.Head(ts.URL)
   705  	got := <-ch
   706  	want := "proxy for " + ts.URL + "/"
   707  	if got != want {
   708  		t.Errorf("want %q, got %q", want, got)
   709  	}
   710  }
   711  
   712  // TestTransportGzipRecursive sends a gzip quine and checks that the
   713  // client gets the same value back. This is more cute than anything,
   714  // but checks that we don't recurse forever, and checks that
   715  // Content-Encoding is removed.
   716  func TestTransportGzipRecursive(t *testing.T) {
   717  	defer afterTest(t)
   718  	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
   719  		w.Header().Set("Content-Encoding", "gzip")
   720  		w.Write(rgz)
   721  	}))
   722  	defer ts.Close()
   723  
   724  	c := &Client{Transport: &Transport{}}
   725  	res, err := c.Get(ts.URL)
   726  	if err != nil {
   727  		t.Fatal(err)
   728  	}
   729  	body, err := ioutil.ReadAll(res.Body)
   730  	if err != nil {
   731  		t.Fatal(err)
   732  	}
   733  	if !bytes.Equal(body, rgz) {
   734  		t.Fatalf("Incorrect result from recursive gz:\nhave=%x\nwant=%x",
   735  			body, rgz)
   736  	}
   737  	if g, e := res.Header.Get("Content-Encoding"), ""; g != e {
   738  		t.Fatalf("Content-Encoding = %q; want %q", g, e)
   739  	}
   740  }
   741  
   742  // tests that persistent goroutine connections shut down when no longer desired.
   743  func TestTransportPersistConnLeak(t *testing.T) {
   744  	defer afterTest(t)
   745  	gotReqCh := make(chan bool)
   746  	unblockCh := make(chan bool)
   747  	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
   748  		gotReqCh <- true
   749  		<-unblockCh
   750  		w.Header().Set("Content-Length", "0")
   751  		w.WriteHeader(204)
   752  	}))
   753  	defer ts.Close()
   754  
   755  	tr := &Transport{}
   756  	c := &Client{Transport: tr}
   757  
   758  	n0 := runtime.NumGoroutine()
   759  
   760  	const numReq = 25
   761  	didReqCh := make(chan bool)
   762  	for i := 0; i < numReq; i++ {
   763  		go func() {
   764  			res, err := c.Get(ts.URL)
   765  			didReqCh <- true
   766  			if err != nil {
   767  				t.Errorf("client fetch error: %v", err)
   768  				return
   769  			}
   770  			res.Body.Close()
   771  		}()
   772  	}
   773  
   774  	// Wait for all goroutines to be stuck in the Handler.
   775  	for i := 0; i < numReq; i++ {
   776  		<-gotReqCh
   777  	}
   778  
   779  	nhigh := runtime.NumGoroutine()
   780  
   781  	// Tell all handlers to unblock and reply.
   782  	for i := 0; i < numReq; i++ {
   783  		unblockCh <- true
   784  	}
   785  
   786  	// Wait for all HTTP clients to be done.
   787  	for i := 0; i < numReq; i++ {
   788  		<-didReqCh
   789  	}
   790  
   791  	tr.CloseIdleConnections()
   792  	time.Sleep(100 * time.Millisecond)
   793  	runtime.GC()
   794  	runtime.GC() // even more.
   795  	nfinal := runtime.NumGoroutine()
   796  
   797  	growth := nfinal - n0
   798  
   799  	// We expect 0 or 1 extra goroutine, empirically.  Allow up to 5.
   800  	// Previously we were leaking one per numReq.
   801  	t.Logf("goroutine growth: %d -> %d -> %d (delta: %d)", n0, nhigh, nfinal, growth)
   802  	if int(growth) > 5 {
   803  		t.Error("too many new goroutines")
   804  	}
   805  }
   806  
   807  // golang.org/issue/4531: Transport leaks goroutines when
   808  // request.ContentLength is explicitly short
   809  func TestTransportPersistConnLeakShortBody(t *testing.T) {
   810  	defer afterTest(t)
   811  	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
   812  	}))
   813  	defer ts.Close()
   814  
   815  	tr := &Transport{}
   816  	c := &Client{Transport: tr}
   817  
   818  	n0 := runtime.NumGoroutine()
   819  	body := []byte("Hello")
   820  	for i := 0; i < 20; i++ {
   821  		req, err := NewRequest("POST", ts.URL, bytes.NewReader(body))
   822  		if err != nil {
   823  			t.Fatal(err)
   824  		}
   825  		req.ContentLength = int64(len(body) - 2) // explicitly short
   826  		_, err = c.Do(req)
   827  		if err == nil {
   828  			t.Fatal("Expect an error from writing too long of a body.")
   829  		}
   830  	}
   831  	nhigh := runtime.NumGoroutine()
   832  	tr.CloseIdleConnections()
   833  	time.Sleep(400 * time.Millisecond)
   834  	runtime.GC()
   835  	nfinal := runtime.NumGoroutine()
   836  
   837  	growth := nfinal - n0
   838  
   839  	// We expect 0 or 1 extra goroutine, empirically.  Allow up to 5.
   840  	// Previously we were leaking one per numReq.
   841  	t.Logf("goroutine growth: %d -> %d -> %d (delta: %d)", n0, nhigh, nfinal, growth)
   842  	if int(growth) > 5 {
   843  		t.Error("too many new goroutines")
   844  	}
   845  }
   846  
   847  // This used to crash; http://golang.org/issue/3266
   848  func TestTransportIdleConnCrash(t *testing.T) {
   849  	defer afterTest(t)
   850  	tr := &Transport{}
   851  	c := &Client{Transport: tr}
   852  
   853  	unblockCh := make(chan bool, 1)
   854  	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
   855  		<-unblockCh
   856  		tr.CloseIdleConnections()
   857  	}))
   858  	defer ts.Close()
   859  
   860  	didreq := make(chan bool)
   861  	go func() {
   862  		res, err := c.Get(ts.URL)
   863  		if err != nil {
   864  			t.Error(err)
   865  		} else {
   866  			res.Body.Close() // returns idle conn
   867  		}
   868  		didreq <- true
   869  	}()
   870  	unblockCh <- true
   871  	<-didreq
   872  }
   873  
   874  // Test that the transport doesn't close the TCP connection early,
   875  // before the response body has been read.  This was a regression
   876  // which sadly lacked a triggering test.  The large response body made
   877  // the old race easier to trigger.
   878  func TestIssue3644(t *testing.T) {
   879  	defer afterTest(t)
   880  	const numFoos = 5000
   881  	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
   882  		w.Header().Set("Connection", "close")
   883  		for i := 0; i < numFoos; i++ {
   884  			w.Write([]byte("foo "))
   885  		}
   886  	}))
   887  	defer ts.Close()
   888  	tr := &Transport{}
   889  	c := &Client{Transport: tr}
   890  	res, err := c.Get(ts.URL)
   891  	if err != nil {
   892  		t.Fatal(err)
   893  	}
   894  	defer res.Body.Close()
   895  	bs, err := ioutil.ReadAll(res.Body)
   896  	if err != nil {
   897  		t.Fatal(err)
   898  	}
   899  	if len(bs) != numFoos*len("foo ") {
   900  		t.Errorf("unexpected response length")
   901  	}
   902  }
   903  
   904  // Test that a client receives a server's reply, even if the server doesn't read
   905  // the entire request body.
   906  func TestIssue3595(t *testing.T) {
   907  	defer afterTest(t)
   908  	const deniedMsg = "sorry, denied."
   909  	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
   910  		Error(w, deniedMsg, StatusUnauthorized)
   911  	}))
   912  	defer ts.Close()
   913  	tr := &Transport{}
   914  	c := &Client{Transport: tr}
   915  	res, err := c.Post(ts.URL, "application/octet-stream", neverEnding('a'))
   916  	if err != nil {
   917  		t.Errorf("Post: %v", err)
   918  		return
   919  	}
   920  	got, err := ioutil.ReadAll(res.Body)
   921  	if err != nil {
   922  		t.Fatalf("Body ReadAll: %v", err)
   923  	}
   924  	if !strings.Contains(string(got), deniedMsg) {
   925  		t.Errorf("Known bug: response %q does not contain %q", got, deniedMsg)
   926  	}
   927  }
   928  
   929  // From http://golang.org/issue/4454 ,
   930  // "client fails to handle requests with no body and chunked encoding"
   931  func TestChunkedNoContent(t *testing.T) {
   932  	defer afterTest(t)
   933  	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
   934  		w.WriteHeader(StatusNoContent)
   935  	}))
   936  	defer ts.Close()
   937  
   938  	for _, closeBody := range []bool{true, false} {
   939  		c := &Client{Transport: &Transport{}}
   940  		const n = 4
   941  		for i := 1; i <= n; i++ {
   942  			res, err := c.Get(ts.URL)
   943  			if err != nil {
   944  				t.Errorf("closingBody=%v, req %d/%d: %v", closeBody, i, n, err)
   945  			} else {
   946  				if closeBody {
   947  					res.Body.Close()
   948  				}
   949  			}
   950  		}
   951  	}
   952  }
   953  
   954  func TestTransportConcurrency(t *testing.T) {
   955  	defer afterTest(t)
   956  	maxProcs, numReqs := 16, 500
   957  	if testing.Short() {
   958  		maxProcs, numReqs = 4, 50
   959  	}
   960  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs))
   961  	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
   962  		fmt.Fprintf(w, "%v", r.FormValue("echo"))
   963  	}))
   964  	defer ts.Close()
   965  
   966  	var wg sync.WaitGroup
   967  	wg.Add(numReqs)
   968  
   969  	tr := &Transport{
   970  		Dial: func(netw, addr string) (c net.Conn, err error) {
   971  			// Due to the Transport's "socket late
   972  			// binding" (see idleConnCh in transport.go),
   973  			// the numReqs HTTP requests below can finish
   974  			// with a dial still outstanding.  So count
   975  			// our dials as work too so the leak checker
   976  			// doesn't complain at us.
   977  			wg.Add(1)
   978  			defer wg.Done()
   979  			return net.Dial(netw, addr)
   980  		},
   981  	}
   982  	defer tr.CloseIdleConnections()
   983  	c := &Client{Transport: tr}
   984  	reqs := make(chan string)
   985  	defer close(reqs)
   986  
   987  	for i := 0; i < maxProcs*2; i++ {
   988  		go func() {
   989  			for req := range reqs {
   990  				res, err := c.Get(ts.URL + "/?echo=" + req)
   991  				if err != nil {
   992  					t.Errorf("error on req %s: %v", req, err)
   993  					wg.Done()
   994  					continue
   995  				}
   996  				all, err := ioutil.ReadAll(res.Body)
   997  				if err != nil {
   998  					t.Errorf("read error on req %s: %v", req, err)
   999  					wg.Done()
  1000  					continue
  1001  				}
  1002  				if string(all) != req {
  1003  					t.Errorf("body of req %s = %q; want %q", req, all, req)
  1004  				}
  1005  				res.Body.Close()
  1006  				wg.Done()
  1007  			}
  1008  		}()
  1009  	}
  1010  	for i := 0; i < numReqs; i++ {
  1011  		reqs <- fmt.Sprintf("request-%d", i)
  1012  	}
  1013  	wg.Wait()
  1014  }
  1015  
  1016  func TestIssue4191_InfiniteGetTimeout(t *testing.T) {
  1017  	defer afterTest(t)
  1018  	const debug = false
  1019  	mux := NewServeMux()
  1020  	mux.HandleFunc("/get", func(w ResponseWriter, r *Request) {
  1021  		io.Copy(w, neverEnding('a'))
  1022  	})
  1023  	ts := httptest.NewServer(mux)
  1024  	timeout := 100 * time.Millisecond
  1025  
  1026  	client := &Client{
  1027  		Transport: &Transport{
  1028  			Dial: func(n, addr string) (net.Conn, error) {
  1029  				conn, err := net.Dial(n, addr)
  1030  				if err != nil {
  1031  					return nil, err
  1032  				}
  1033  				conn.SetDeadline(time.Now().Add(timeout))
  1034  				if debug {
  1035  					conn = NewLoggingConn("client", conn)
  1036  				}
  1037  				return conn, nil
  1038  			},
  1039  			DisableKeepAlives: true,
  1040  		},
  1041  	}
  1042  
  1043  	getFailed := false
  1044  	nRuns := 5
  1045  	if testing.Short() {
  1046  		nRuns = 1
  1047  	}
  1048  	for i := 0; i < nRuns; i++ {
  1049  		if debug {
  1050  			println("run", i+1, "of", nRuns)
  1051  		}
  1052  		sres, err := client.Get(ts.URL + "/get")
  1053  		if err != nil {
  1054  			if !getFailed {
  1055  				// Make the timeout longer, once.
  1056  				getFailed = true
  1057  				t.Logf("increasing timeout")
  1058  				i--
  1059  				timeout *= 10
  1060  				continue
  1061  			}
  1062  			t.Errorf("Error issuing GET: %v", err)
  1063  			break
  1064  		}
  1065  		_, err = io.Copy(ioutil.Discard, sres.Body)
  1066  		if err == nil {
  1067  			t.Errorf("Unexpected successful copy")
  1068  			break
  1069  		}
  1070  	}
  1071  	if debug {
  1072  		println("tests complete; waiting for handlers to finish")
  1073  	}
  1074  	ts.Close()
  1075  }
  1076  
  1077  func TestIssue4191_InfiniteGetToPutTimeout(t *testing.T) {
  1078  	defer afterTest(t)
  1079  	const debug = false
  1080  	mux := NewServeMux()
  1081  	mux.HandleFunc("/get", func(w ResponseWriter, r *Request) {
  1082  		io.Copy(w, neverEnding('a'))
  1083  	})
  1084  	mux.HandleFunc("/put", func(w ResponseWriter, r *Request) {
  1085  		defer r.Body.Close()
  1086  		io.Copy(ioutil.Discard, r.Body)
  1087  	})
  1088  	ts := httptest.NewServer(mux)
  1089  	timeout := 100 * time.Millisecond
  1090  
  1091  	client := &Client{
  1092  		Transport: &Transport{
  1093  			Dial: func(n, addr string) (net.Conn, error) {
  1094  				conn, err := net.Dial(n, addr)
  1095  				if err != nil {
  1096  					return nil, err
  1097  				}
  1098  				conn.SetDeadline(time.Now().Add(timeout))
  1099  				if debug {
  1100  					conn = NewLoggingConn("client", conn)
  1101  				}
  1102  				return conn, nil
  1103  			},
  1104  			DisableKeepAlives: true,
  1105  		},
  1106  	}
  1107  
  1108  	getFailed := false
  1109  	nRuns := 5
  1110  	if testing.Short() {
  1111  		nRuns = 1
  1112  	}
  1113  	for i := 0; i < nRuns; i++ {
  1114  		if debug {
  1115  			println("run", i+1, "of", nRuns)
  1116  		}
  1117  		sres, err := client.Get(ts.URL + "/get")
  1118  		if err != nil {
  1119  			if !getFailed {
  1120  				// Make the timeout longer, once.
  1121  				getFailed = true
  1122  				t.Logf("increasing timeout")
  1123  				i--
  1124  				timeout *= 10
  1125  				continue
  1126  			}
  1127  			t.Errorf("Error issuing GET: %v", err)
  1128  			break
  1129  		}
  1130  		req, _ := NewRequest("PUT", ts.URL+"/put", sres.Body)
  1131  		_, err = client.Do(req)
  1132  		if err == nil {
  1133  			sres.Body.Close()
  1134  			t.Errorf("Unexpected successful PUT")
  1135  			break
  1136  		}
  1137  		sres.Body.Close()
  1138  	}
  1139  	if debug {
  1140  		println("tests complete; waiting for handlers to finish")
  1141  	}
  1142  	ts.Close()
  1143  }
  1144  
  1145  func TestTransportResponseHeaderTimeout(t *testing.T) {
  1146  	defer afterTest(t)
  1147  	if testing.Short() {
  1148  		t.Skip("skipping timeout test in -short mode")
  1149  	}
  1150  	mux := NewServeMux()
  1151  	mux.HandleFunc("/fast", func(w ResponseWriter, r *Request) {})
  1152  	mux.HandleFunc("/slow", func(w ResponseWriter, r *Request) {
  1153  		time.Sleep(2 * time.Second)
  1154  	})
  1155  	ts := httptest.NewServer(mux)
  1156  	defer ts.Close()
  1157  
  1158  	tr := &Transport{
  1159  		ResponseHeaderTimeout: 500 * time.Millisecond,
  1160  	}
  1161  	defer tr.CloseIdleConnections()
  1162  	c := &Client{Transport: tr}
  1163  
  1164  	tests := []struct {
  1165  		path    string
  1166  		want    int
  1167  		wantErr string
  1168  	}{
  1169  		{path: "/fast", want: 200},
  1170  		{path: "/slow", wantErr: "timeout awaiting response headers"},
  1171  		{path: "/fast", want: 200},
  1172  	}
  1173  	for i, tt := range tests {
  1174  		res, err := c.Get(ts.URL + tt.path)
  1175  		if err != nil {
  1176  			if strings.Contains(err.Error(), tt.wantErr) {
  1177  				continue
  1178  			}
  1179  			t.Errorf("%d. unexpected error: %v", i, err)
  1180  			continue
  1181  		}
  1182  		if tt.wantErr != "" {
  1183  			t.Errorf("%d. no error. expected error: %v", i, tt.wantErr)
  1184  			continue
  1185  		}
  1186  		if res.StatusCode != tt.want {
  1187  			t.Errorf("%d for path %q status = %d; want %d", i, tt.path, res.StatusCode, tt.want)
  1188  		}
  1189  	}
  1190  }
  1191  
  1192  func TestTransportCancelRequest(t *testing.T) {
  1193  	defer afterTest(t)
  1194  	if testing.Short() {
  1195  		t.Skip("skipping test in -short mode")
  1196  	}
  1197  	unblockc := make(chan bool)
  1198  	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
  1199  		fmt.Fprintf(w, "Hello")
  1200  		w.(Flusher).Flush() // send headers and some body
  1201  		<-unblockc
  1202  	}))
  1203  	defer ts.Close()
  1204  	defer close(unblockc)
  1205  
  1206  	tr := &Transport{}
  1207  	defer tr.CloseIdleConnections()
  1208  	c := &Client{Transport: tr}
  1209  
  1210  	req, _ := NewRequest("GET", ts.URL, nil)
  1211  	res, err := c.Do(req)
  1212  	if err != nil {
  1213  		t.Fatal(err)
  1214  	}
  1215  	go func() {
  1216  		time.Sleep(1 * time.Second)
  1217  		tr.CancelRequest(req)
  1218  	}()
  1219  	t0 := time.Now()
  1220  	body, err := ioutil.ReadAll(res.Body)
  1221  	d := time.Since(t0)
  1222  
  1223  	if err == nil {
  1224  		t.Error("expected an error reading the body")
  1225  	}
  1226  	if string(body) != "Hello" {
  1227  		t.Errorf("Body = %q; want Hello", body)
  1228  	}
  1229  	if d < 500*time.Millisecond {
  1230  		t.Errorf("expected ~1 second delay; got %v", d)
  1231  	}
  1232  	// Verify no outstanding requests after readLoop/writeLoop
  1233  	// goroutines shut down.
  1234  	for tries := 3; tries > 0; tries-- {
  1235  		n := tr.NumPendingRequestsForTesting()
  1236  		if n == 0 {
  1237  			break
  1238  		}
  1239  		time.Sleep(100 * time.Millisecond)
  1240  		if tries == 1 {
  1241  			t.Errorf("pending requests = %d; want 0", n)
  1242  		}
  1243  	}
  1244  }
  1245  
  1246  // golang.org/issue/3672 -- Client can't close HTTP stream
  1247  // Calling Close on a Response.Body used to just read until EOF.
  1248  // Now it actually closes the TCP connection.
  1249  func TestTransportCloseResponseBody(t *testing.T) {
  1250  	defer afterTest(t)
  1251  	writeErr := make(chan error, 1)
  1252  	msg := []byte("young\n")
  1253  	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
  1254  		for {
  1255  			_, err := w.Write(msg)
  1256  			if err != nil {
  1257  				writeErr <- err
  1258  				return
  1259  			}
  1260  			w.(Flusher).Flush()
  1261  		}
  1262  	}))
  1263  	defer ts.Close()
  1264  
  1265  	tr := &Transport{}
  1266  	defer tr.CloseIdleConnections()
  1267  	c := &Client{Transport: tr}
  1268  
  1269  	req, _ := NewRequest("GET", ts.URL, nil)
  1270  	defer tr.CancelRequest(req)
  1271  
  1272  	res, err := c.Do(req)
  1273  	if err != nil {
  1274  		t.Fatal(err)
  1275  	}
  1276  
  1277  	const repeats = 3
  1278  	buf := make([]byte, len(msg)*repeats)
  1279  	want := bytes.Repeat(msg, repeats)
  1280  
  1281  	_, err = io.ReadFull(res.Body, buf)
  1282  	if err != nil {
  1283  		t.Fatal(err)
  1284  	}
  1285  	if !bytes.Equal(buf, want) {
  1286  		t.Errorf("read %q; want %q", buf, want)
  1287  	}
  1288  	didClose := make(chan error, 1)
  1289  	go func() {
  1290  		didClose <- res.Body.Close()
  1291  	}()
  1292  	select {
  1293  	case err := <-didClose:
  1294  		if err != nil {
  1295  			t.Errorf("Close = %v", err)
  1296  		}
  1297  	case <-time.After(10 * time.Second):
  1298  		t.Fatal("too long waiting for close")
  1299  	}
  1300  	select {
  1301  	case err := <-writeErr:
  1302  		if err == nil {
  1303  			t.Errorf("expected non-nil write error")
  1304  		}
  1305  	case <-time.After(10 * time.Second):
  1306  		t.Fatal("too long waiting for write error")
  1307  	}
  1308  }
  1309  
  1310  type fooProto struct{}
  1311  
  1312  func (fooProto) RoundTrip(req *Request) (*Response, error) {
  1313  	res := &Response{
  1314  		Status:     "200 OK",
  1315  		StatusCode: 200,
  1316  		Header:     make(Header),
  1317  		Body:       ioutil.NopCloser(strings.NewReader("You wanted " + req.URL.String())),
  1318  	}
  1319  	return res, nil
  1320  }
  1321  
  1322  func TestTransportAltProto(t *testing.T) {
  1323  	defer afterTest(t)
  1324  	tr := &Transport{}
  1325  	c := &Client{Transport: tr}
  1326  	tr.RegisterProtocol("foo", fooProto{})
  1327  	res, err := c.Get("foo://bar.com/path")
  1328  	if err != nil {
  1329  		t.Fatal(err)
  1330  	}
  1331  	bodyb, err := ioutil.ReadAll(res.Body)
  1332  	if err != nil {
  1333  		t.Fatal(err)
  1334  	}
  1335  	body := string(bodyb)
  1336  	if e := "You wanted foo://bar.com/path"; body != e {
  1337  		t.Errorf("got response %q, want %q", body, e)
  1338  	}
  1339  }
  1340  
  1341  func TestTransportNoHost(t *testing.T) {
  1342  	defer afterTest(t)
  1343  	tr := &Transport{}
  1344  	_, err := tr.RoundTrip(&Request{
  1345  		Header: make(Header),
  1346  		URL: &url.URL{
  1347  			Scheme: "http",
  1348  		},
  1349  	})
  1350  	want := "http: no Host in request URL"
  1351  	if got := fmt.Sprint(err); got != want {
  1352  		t.Errorf("error = %v; want %q", err, want)
  1353  	}
  1354  }
  1355  
  1356  func TestTransportSocketLateBinding(t *testing.T) {
  1357  	defer afterTest(t)
  1358  
  1359  	mux := NewServeMux()
  1360  	fooGate := make(chan bool, 1)
  1361  	mux.HandleFunc("/foo", func(w ResponseWriter, r *Request) {
  1362  		w.Header().Set("foo-ipport", r.RemoteAddr)
  1363  		w.(Flusher).Flush()
  1364  		<-fooGate
  1365  	})
  1366  	mux.HandleFunc("/bar", func(w ResponseWriter, r *Request) {
  1367  		w.Header().Set("bar-ipport", r.RemoteAddr)
  1368  	})
  1369  	ts := httptest.NewServer(mux)
  1370  	defer ts.Close()
  1371  
  1372  	dialGate := make(chan bool, 1)
  1373  	tr := &Transport{
  1374  		Dial: func(n, addr string) (net.Conn, error) {
  1375  			<-dialGate
  1376  			return net.Dial(n, addr)
  1377  		},
  1378  		DisableKeepAlives: false,
  1379  	}
  1380  	defer tr.CloseIdleConnections()
  1381  	c := &Client{
  1382  		Transport: tr,
  1383  	}
  1384  
  1385  	dialGate <- true // only allow one dial
  1386  	fooRes, err := c.Get(ts.URL + "/foo")
  1387  	if err != nil {
  1388  		t.Fatal(err)
  1389  	}
  1390  	fooAddr := fooRes.Header.Get("foo-ipport")
  1391  	if fooAddr == "" {
  1392  		t.Fatal("No addr on /foo request")
  1393  	}
  1394  	time.AfterFunc(200*time.Millisecond, func() {
  1395  		// let the foo response finish so we can use its
  1396  		// connection for /bar
  1397  		fooGate <- true
  1398  		io.Copy(ioutil.Discard, fooRes.Body)
  1399  		fooRes.Body.Close()
  1400  	})
  1401  
  1402  	barRes, err := c.Get(ts.URL + "/bar")
  1403  	if err != nil {
  1404  		t.Fatal(err)
  1405  	}
  1406  	barAddr := barRes.Header.Get("bar-ipport")
  1407  	if barAddr != fooAddr {
  1408  		t.Fatalf("/foo came from conn %q; /bar came from %q instead", fooAddr, barAddr)
  1409  	}
  1410  	barRes.Body.Close()
  1411  	dialGate <- true
  1412  }
  1413  
  1414  // Issue 2184
  1415  func TestTransportReading100Continue(t *testing.T) {
  1416  	defer afterTest(t)
  1417  
  1418  	const numReqs = 5
  1419  	reqBody := func(n int) string { return fmt.Sprintf("request body %d", n) }
  1420  	reqID := func(n int) string { return fmt.Sprintf("REQ-ID-%d", n) }
  1421  
  1422  	send100Response := func(w *io.PipeWriter, r *io.PipeReader) {
  1423  		defer w.Close()
  1424  		defer r.Close()
  1425  		br := bufio.NewReader(r)
  1426  		n := 0
  1427  		for {
  1428  			n++
  1429  			req, err := ReadRequest(br)
  1430  			if err == io.EOF {
  1431  				return
  1432  			}
  1433  			if err != nil {
  1434  				t.Error(err)
  1435  				return
  1436  			}
  1437  			slurp, err := ioutil.ReadAll(req.Body)
  1438  			if err != nil {
  1439  				t.Errorf("Server request body slurp: %v", err)
  1440  				return
  1441  			}
  1442  			id := req.Header.Get("Request-Id")
  1443  			resCode := req.Header.Get("X-Want-Response-Code")
  1444  			if resCode == "" {
  1445  				resCode = "100 Continue"
  1446  				if string(slurp) != reqBody(n) {
  1447  					t.Errorf("Server got %q, %v; want %q", slurp, err, reqBody(n))
  1448  				}
  1449  			}
  1450  			body := fmt.Sprintf("Response number %d", n)
  1451  			v := []byte(strings.Replace(fmt.Sprintf(`HTTP/1.1 %s
  1452  Date: Thu, 28 Feb 2013 17:55:41 GMT
  1453  
  1454  HTTP/1.1 200 OK
  1455  Content-Type: text/html
  1456  Echo-Request-Id: %s
  1457  Content-Length: %d
  1458  
  1459  %s`, resCode, id, len(body), body), "\n", "\r\n", -1))
  1460  			w.Write(v)
  1461  			if id == reqID(numReqs) {
  1462  				return
  1463  			}
  1464  		}
  1465  
  1466  	}
  1467  
  1468  	tr := &Transport{
  1469  		Dial: func(n, addr string) (net.Conn, error) {
  1470  			sr, sw := io.Pipe() // server read/write
  1471  			cr, cw := io.Pipe() // client read/write
  1472  			conn := &rwTestConn{
  1473  				Reader: cr,
  1474  				Writer: sw,
  1475  				closeFunc: func() error {
  1476  					sw.Close()
  1477  					cw.Close()
  1478  					return nil
  1479  				},
  1480  			}
  1481  			go send100Response(cw, sr)
  1482  			return conn, nil
  1483  		},
  1484  		DisableKeepAlives: false,
  1485  	}
  1486  	defer tr.CloseIdleConnections()
  1487  	c := &Client{Transport: tr}
  1488  
  1489  	testResponse := func(req *Request, name string, wantCode int) {
  1490  		res, err := c.Do(req)
  1491  		if err != nil {
  1492  			t.Fatalf("%s: Do: %v", name, err)
  1493  		}
  1494  		if res.StatusCode != wantCode {
  1495  			t.Fatalf("%s: Response Statuscode=%d; want %d", name, res.StatusCode, wantCode)
  1496  		}
  1497  		if id, idBack := req.Header.Get("Request-Id"), res.Header.Get("Echo-Request-Id"); id != "" && id != idBack {
  1498  			t.Errorf("%s: response id %q != request id %q", name, idBack, id)
  1499  		}
  1500  		_, err = ioutil.ReadAll(res.Body)
  1501  		if err != nil {
  1502  			t.Fatalf("%s: Slurp error: %v", name, err)
  1503  		}
  1504  	}
  1505  
  1506  	// Few 100 responses, making sure we're not off-by-one.
  1507  	for i := 1; i <= numReqs; i++ {
  1508  		req, _ := NewRequest("POST", "http://dummy.tld/", strings.NewReader(reqBody(i)))
  1509  		req.Header.Set("Request-Id", reqID(i))
  1510  		testResponse(req, fmt.Sprintf("100, %d/%d", i, numReqs), 200)
  1511  	}
  1512  
  1513  	// And some other informational 1xx but non-100 responses, to test
  1514  	// we return them but don't re-use the connection.
  1515  	for i := 1; i <= numReqs; i++ {
  1516  		req, _ := NewRequest("POST", "http://other.tld/", strings.NewReader(reqBody(i)))
  1517  		req.Header.Set("X-Want-Response-Code", "123 Sesame Street")
  1518  		testResponse(req, fmt.Sprintf("123, %d/%d", i, numReqs), 123)
  1519  	}
  1520  }
  1521  
  1522  type proxyFromEnvTest struct {
  1523  	req     string // URL to fetch; blank means "http://example.com"
  1524  	env     string
  1525  	noenv   string
  1526  	want    string
  1527  	wanterr error
  1528  }
  1529  
  1530  func (t proxyFromEnvTest) String() string {
  1531  	var buf bytes.Buffer
  1532  	if t.env != "" {
  1533  		fmt.Fprintf(&buf, "http_proxy=%q", t.env)
  1534  	}
  1535  	if t.noenv != "" {
  1536  		fmt.Fprintf(&buf, " no_proxy=%q", t.noenv)
  1537  	}
  1538  	req := "http://example.com"
  1539  	if t.req != "" {
  1540  		req = t.req
  1541  	}
  1542  	fmt.Fprintf(&buf, " req=%q", req)
  1543  	return strings.TrimSpace(buf.String())
  1544  }
  1545  
  1546  var proxyFromEnvTests = []proxyFromEnvTest{
  1547  	{env: "127.0.0.1:8080", want: "http://127.0.0.1:8080"},
  1548  	{env: "cache.corp.example.com:1234", want: "http://cache.corp.example.com:1234"},
  1549  	{env: "cache.corp.example.com", want: "http://cache.corp.example.com"},
  1550  	{env: "https://cache.corp.example.com", want: "https://cache.corp.example.com"},
  1551  	{env: "http://127.0.0.1:8080", want: "http://127.0.0.1:8080"},
  1552  	{env: "https://127.0.0.1:8080", want: "https://127.0.0.1:8080"},
  1553  	{want: "<nil>"},
  1554  	{noenv: "example.com", req: "http://example.com/", env: "proxy", want: "<nil>"},
  1555  	{noenv: ".example.com", req: "http://example.com/", env: "proxy", want: "<nil>"},
  1556  	{noenv: "ample.com", req: "http://example.com/", env: "proxy", want: "http://proxy"},
  1557  	{noenv: "example.com", req: "http://foo.example.com/", env: "proxy", want: "<nil>"},
  1558  	{noenv: ".foo.com", req: "http://example.com/", env: "proxy", want: "http://proxy"},
  1559  }
  1560  
  1561  func TestProxyFromEnvironment(t *testing.T) {
  1562  	os.Setenv("HTTP_PROXY", "")
  1563  	os.Setenv("http_proxy", "")
  1564  	os.Setenv("NO_PROXY", "")
  1565  	os.Setenv("no_proxy", "")
  1566  	for _, tt := range proxyFromEnvTests {
  1567  		os.Setenv("HTTP_PROXY", tt.env)
  1568  		os.Setenv("NO_PROXY", tt.noenv)
  1569  		reqURL := tt.req
  1570  		if reqURL == "" {
  1571  			reqURL = "http://example.com"
  1572  		}
  1573  		req, _ := NewRequest("GET", reqURL, nil)
  1574  		url, err := ProxyFromEnvironment(req)
  1575  		if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e {
  1576  			t.Errorf("%v: got error = %q, want %q", tt, g, e)
  1577  			continue
  1578  		}
  1579  		if got := fmt.Sprintf("%s", url); got != tt.want {
  1580  			t.Errorf("%v: got URL = %q, want %q", tt, url, tt.want)
  1581  		}
  1582  	}
  1583  }
  1584  
  1585  func TestIdleConnChannelLeak(t *testing.T) {
  1586  	var mu sync.Mutex
  1587  	var n int
  1588  
  1589  	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
  1590  		mu.Lock()
  1591  		n++
  1592  		mu.Unlock()
  1593  	}))
  1594  	defer ts.Close()
  1595  
  1596  	tr := &Transport{
  1597  		Dial: func(netw, addr string) (net.Conn, error) {
  1598  			return net.Dial(netw, ts.Listener.Addr().String())
  1599  		},
  1600  	}
  1601  	defer tr.CloseIdleConnections()
  1602  
  1603  	c := &Client{Transport: tr}
  1604  
  1605  	// First, without keep-alives.
  1606  	for _, disableKeep := range []bool{true, false} {
  1607  		tr.DisableKeepAlives = disableKeep
  1608  		for i := 0; i < 5; i++ {
  1609  			_, err := c.Get(fmt.Sprintf("http://foo-host-%d.tld/", i))
  1610  			if err != nil {
  1611  				t.Fatal(err)
  1612  			}
  1613  		}
  1614  		if got := tr.IdleConnChMapSizeForTesting(); got != 0 {
  1615  			t.Fatalf("ForDisableKeepAlives = %v, map size = %d; want 0", disableKeep, got)
  1616  		}
  1617  	}
  1618  }
  1619  
  1620  // Verify the status quo: that the Client.Post function coerces its
  1621  // body into a ReadCloser if it's a Closer, and that the Transport
  1622  // then closes it.
  1623  func TestTransportClosesRequestBody(t *testing.T) {
  1624  	defer afterTest(t)
  1625  	ts := httptest.NewServer(http.HandlerFunc(func(w ResponseWriter, r *Request) {
  1626  		io.Copy(ioutil.Discard, r.Body)
  1627  	}))
  1628  	defer ts.Close()
  1629  
  1630  	tr := &Transport{}
  1631  	defer tr.CloseIdleConnections()
  1632  	cl := &Client{Transport: tr}
  1633  
  1634  	closes := 0
  1635  
  1636  	res, err := cl.Post(ts.URL, "text/plain", countCloseReader{&closes, strings.NewReader("hello")})
  1637  	if err != nil {
  1638  		t.Fatal(err)
  1639  	}
  1640  	res.Body.Close()
  1641  	if closes != 1 {
  1642  		t.Errorf("closes = %d; want 1", closes)
  1643  	}
  1644  }
  1645  
  1646  type countCloseReader struct {
  1647  	n *int
  1648  	io.Reader
  1649  }
  1650  
  1651  func (cr countCloseReader) Close() error {
  1652  	(*cr.n)++
  1653  	return nil
  1654  }
  1655  
  1656  // rgz is a gzip quine that uncompresses to itself.
  1657  var rgz = []byte{
  1658  	0x1f, 0x8b, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
  1659  	0x00, 0x00, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73,
  1660  	0x69, 0x76, 0x65, 0x00, 0x92, 0xef, 0xe6, 0xe0,
  1661  	0x60, 0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2,
  1662  	0xe2, 0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17,
  1663  	0x00, 0xe8, 0xff, 0x92, 0xef, 0xe6, 0xe0, 0x60,
  1664  	0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2, 0xe2,
  1665  	0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17, 0x00,
  1666  	0xe8, 0xff, 0x42, 0x12, 0x46, 0x16, 0x06, 0x00,
  1667  	0x05, 0x00, 0xfa, 0xff, 0x42, 0x12, 0x46, 0x16,
  1668  	0x06, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00, 0x05,
  1669  	0x00, 0xfa, 0xff, 0x00, 0x14, 0x00, 0xeb, 0xff,
  1670  	0x42, 0x12, 0x46, 0x16, 0x06, 0x00, 0x05, 0x00,
  1671  	0xfa, 0xff, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00,
  1672  	0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4,
  1673  	0x00, 0x00, 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88,
  1674  	0x21, 0xc4, 0x00, 0x00, 0x14, 0x00, 0xeb, 0xff,
  1675  	0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x14, 0x00,
  1676  	0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00,
  1677  	0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4,
  1678  	0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
  1679  	0x00, 0xff, 0xff, 0x00, 0x17, 0x00, 0xe8, 0xff,
  1680  	0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x00, 0x00,
  1681  	0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
  1682  	0x17, 0x00, 0xe8, 0xff, 0x42, 0x12, 0x46, 0x16,
  1683  	0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08,
  1684  	0x00, 0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa,
  1685  	0x00, 0x00, 0x00, 0x42, 0x12, 0x46, 0x16, 0x06,
  1686  	0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08, 0x00,
  1687  	0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00,
  1688  	0x00, 0x00, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00,
  1689  	0x00, 0x00,
  1690  }