libgo: update to Go 1.11
[official-gcc.git] / libgo / go / net / http / transport_test.go
blobaa8beb9357c8831fc515061662c36580f3282183
1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Tests for transport.go.
6 //
7 // More tests are in clientserver_test.go (for things testing both client & server for both
8 // HTTP/1 and HTTP/2). This
10 package http_test
12 import (
13 "bufio"
14 "bytes"
15 "compress/gzip"
16 "context"
17 "crypto/rand"
18 "crypto/tls"
19 "crypto/x509"
20 "encoding/binary"
21 "errors"
22 "fmt"
23 "internal/nettrace"
24 "internal/testenv"
25 "io"
26 "io/ioutil"
27 "log"
28 "net"
29 . "net/http"
30 "net/http/httptest"
31 "net/http/httptrace"
32 "net/http/httputil"
33 "net/http/internal"
34 "net/textproto"
35 "net/url"
36 "os"
37 "reflect"
38 "runtime"
39 "strconv"
40 "strings"
41 "sync"
42 "sync/atomic"
43 "testing"
44 "time"
47 // TODO: test 5 pipelined requests with responses: 1) OK, 2) OK, Connection: Close
48 // and then verify that the final 2 responses get errors back.
50 // hostPortHandler writes back the client's "host:port".
51 var hostPortHandler = HandlerFunc(func(w ResponseWriter, r *Request) {
52 if r.FormValue("close") == "true" {
53 w.Header().Set("Connection", "close")
55 w.Header().Set("X-Saw-Close", fmt.Sprint(r.Close))
56 w.Write([]byte(r.RemoteAddr))
59 // testCloseConn is a net.Conn tracked by a testConnSet.
60 type testCloseConn struct {
61 net.Conn
62 set *testConnSet
65 func (c *testCloseConn) Close() error {
66 c.set.remove(c)
67 return c.Conn.Close()
70 // testConnSet tracks a set of TCP connections and whether they've
71 // been closed.
72 type testConnSet struct {
73 t *testing.T
74 mu sync.Mutex // guards closed and list
75 closed map[net.Conn]bool
76 list []net.Conn // in order created
79 func (tcs *testConnSet) insert(c net.Conn) {
80 tcs.mu.Lock()
81 defer tcs.mu.Unlock()
82 tcs.closed[c] = false
83 tcs.list = append(tcs.list, c)
86 func (tcs *testConnSet) remove(c net.Conn) {
87 tcs.mu.Lock()
88 defer tcs.mu.Unlock()
89 tcs.closed[c] = true
92 // some tests use this to manage raw tcp connections for later inspection
93 func makeTestDial(t *testing.T) (*testConnSet, func(n, addr string) (net.Conn, error)) {
94 connSet := &testConnSet{
95 t: t,
96 closed: make(map[net.Conn]bool),
98 dial := func(n, addr string) (net.Conn, error) {
99 c, err := net.Dial(n, addr)
100 if err != nil {
101 return nil, err
103 tc := &testCloseConn{c, connSet}
104 connSet.insert(tc)
105 return tc, nil
107 return connSet, dial
110 func (tcs *testConnSet) check(t *testing.T) {
111 tcs.mu.Lock()
112 defer tcs.mu.Unlock()
113 for i := 4; i >= 0; i-- {
114 for i, c := range tcs.list {
115 if tcs.closed[c] {
116 continue
118 if i != 0 {
119 tcs.mu.Unlock()
120 time.Sleep(50 * time.Millisecond)
121 tcs.mu.Lock()
122 continue
124 t.Errorf("TCP connection #%d, %p (of %d total) was not closed", i+1, c, len(tcs.list))
129 func TestReuseRequest(t *testing.T) {
130 defer afterTest(t)
131 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
132 w.Write([]byte("{}"))
134 defer ts.Close()
136 c := ts.Client()
137 req, _ := NewRequest("GET", ts.URL, nil)
138 res, err := c.Do(req)
139 if err != nil {
140 t.Fatal(err)
142 err = res.Body.Close()
143 if err != nil {
144 t.Fatal(err)
147 res, err = c.Do(req)
148 if err != nil {
149 t.Fatal(err)
151 err = res.Body.Close()
152 if err != nil {
153 t.Fatal(err)
157 // Two subsequent requests and verify their response is the same.
158 // The response from the server is our own IP:port
159 func TestTransportKeepAlives(t *testing.T) {
160 defer afterTest(t)
161 ts := httptest.NewServer(hostPortHandler)
162 defer ts.Close()
164 c := ts.Client()
165 for _, disableKeepAlive := range []bool{false, true} {
166 c.Transport.(*Transport).DisableKeepAlives = disableKeepAlive
167 fetch := func(n int) string {
168 res, err := c.Get(ts.URL)
169 if err != nil {
170 t.Fatalf("error in disableKeepAlive=%v, req #%d, GET: %v", disableKeepAlive, n, err)
172 body, err := ioutil.ReadAll(res.Body)
173 if err != nil {
174 t.Fatalf("error in disableKeepAlive=%v, req #%d, ReadAll: %v", disableKeepAlive, n, err)
176 return string(body)
179 body1 := fetch(1)
180 body2 := fetch(2)
182 bodiesDiffer := body1 != body2
183 if bodiesDiffer != disableKeepAlive {
184 t.Errorf("error in disableKeepAlive=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
185 disableKeepAlive, bodiesDiffer, body1, body2)
190 func TestTransportConnectionCloseOnResponse(t *testing.T) {
191 defer afterTest(t)
192 ts := httptest.NewServer(hostPortHandler)
193 defer ts.Close()
195 connSet, testDial := makeTestDial(t)
197 c := ts.Client()
198 tr := c.Transport.(*Transport)
199 tr.Dial = testDial
201 for _, connectionClose := range []bool{false, true} {
202 fetch := func(n int) string {
203 req := new(Request)
204 var err error
205 req.URL, err = url.Parse(ts.URL + fmt.Sprintf("/?close=%v", connectionClose))
206 if err != nil {
207 t.Fatalf("URL parse error: %v", err)
209 req.Method = "GET"
210 req.Proto = "HTTP/1.1"
211 req.ProtoMajor = 1
212 req.ProtoMinor = 1
214 res, err := c.Do(req)
215 if err != nil {
216 t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err)
218 defer res.Body.Close()
219 body, err := ioutil.ReadAll(res.Body)
220 if err != nil {
221 t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err)
223 return string(body)
226 body1 := fetch(1)
227 body2 := fetch(2)
228 bodiesDiffer := body1 != body2
229 if bodiesDiffer != connectionClose {
230 t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
231 connectionClose, bodiesDiffer, body1, body2)
234 tr.CloseIdleConnections()
237 connSet.check(t)
240 func TestTransportConnectionCloseOnRequest(t *testing.T) {
241 defer afterTest(t)
242 ts := httptest.NewServer(hostPortHandler)
243 defer ts.Close()
245 connSet, testDial := makeTestDial(t)
247 c := ts.Client()
248 tr := c.Transport.(*Transport)
249 tr.Dial = testDial
250 for _, connectionClose := range []bool{false, true} {
251 fetch := func(n int) string {
252 req := new(Request)
253 var err error
254 req.URL, err = url.Parse(ts.URL)
255 if err != nil {
256 t.Fatalf("URL parse error: %v", err)
258 req.Method = "GET"
259 req.Proto = "HTTP/1.1"
260 req.ProtoMajor = 1
261 req.ProtoMinor = 1
262 req.Close = connectionClose
264 res, err := c.Do(req)
265 if err != nil {
266 t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err)
268 if got, want := res.Header.Get("X-Saw-Close"), fmt.Sprint(connectionClose); got != want {
269 t.Errorf("For connectionClose = %v; handler's X-Saw-Close was %v; want %v",
270 connectionClose, got, !connectionClose)
272 body, err := ioutil.ReadAll(res.Body)
273 if err != nil {
274 t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err)
276 return string(body)
279 body1 := fetch(1)
280 body2 := fetch(2)
281 bodiesDiffer := body1 != body2
282 if bodiesDiffer != connectionClose {
283 t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
284 connectionClose, bodiesDiffer, body1, body2)
287 tr.CloseIdleConnections()
290 connSet.check(t)
293 // if the Transport's DisableKeepAlives is set, all requests should
294 // send Connection: close.
295 // HTTP/1-only (Connection: close doesn't exist in h2)
296 func TestTransportConnectionCloseOnRequestDisableKeepAlive(t *testing.T) {
297 defer afterTest(t)
298 ts := httptest.NewServer(hostPortHandler)
299 defer ts.Close()
301 c := ts.Client()
302 c.Transport.(*Transport).DisableKeepAlives = true
304 res, err := c.Get(ts.URL)
305 if err != nil {
306 t.Fatal(err)
308 res.Body.Close()
309 if res.Header.Get("X-Saw-Close") != "true" {
310 t.Errorf("handler didn't see Connection: close ")
314 func TestTransportIdleCacheKeys(t *testing.T) {
315 defer afterTest(t)
316 ts := httptest.NewServer(hostPortHandler)
317 defer ts.Close()
318 c := ts.Client()
319 tr := c.Transport.(*Transport)
321 if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g {
322 t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g)
325 resp, err := c.Get(ts.URL)
326 if err != nil {
327 t.Error(err)
329 ioutil.ReadAll(resp.Body)
331 keys := tr.IdleConnKeysForTesting()
332 if e, g := 1, len(keys); e != g {
333 t.Fatalf("After Get expected %d idle conn cache keys; got %d", e, g)
336 if e := "|http|" + ts.Listener.Addr().String(); keys[0] != e {
337 t.Errorf("Expected idle cache key %q; got %q", e, keys[0])
340 tr.CloseIdleConnections()
341 if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g {
342 t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g)
346 // Tests that the HTTP transport re-uses connections when a client
347 // reads to the end of a response Body without closing it.
348 func TestTransportReadToEndReusesConn(t *testing.T) {
349 defer afterTest(t)
350 const msg = "foobar"
352 var addrSeen map[string]int
353 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
354 addrSeen[r.RemoteAddr]++
355 if r.URL.Path == "/chunked/" {
356 w.WriteHeader(200)
357 w.(Flusher).Flush()
358 } else {
359 w.Header().Set("Content-Type", strconv.Itoa(len(msg)))
360 w.WriteHeader(200)
362 w.Write([]byte(msg))
364 defer ts.Close()
366 buf := make([]byte, len(msg))
368 for pi, path := range []string{"/content-length/", "/chunked/"} {
369 wantLen := []int{len(msg), -1}[pi]
370 addrSeen = make(map[string]int)
371 for i := 0; i < 3; i++ {
372 res, err := Get(ts.URL + path)
373 if err != nil {
374 t.Errorf("Get %s: %v", path, err)
375 continue
377 // We want to close this body eventually (before the
378 // defer afterTest at top runs), but not before the
379 // len(addrSeen) check at the bottom of this test,
380 // since Closing this early in the loop would risk
381 // making connections be re-used for the wrong reason.
382 defer res.Body.Close()
384 if res.ContentLength != int64(wantLen) {
385 t.Errorf("%s res.ContentLength = %d; want %d", path, res.ContentLength, wantLen)
387 n, err := res.Body.Read(buf)
388 if n != len(msg) || err != io.EOF {
389 t.Errorf("%s Read = %v, %v; want %d, EOF", path, n, err, len(msg))
392 if len(addrSeen) != 1 {
393 t.Errorf("for %s, server saw %d distinct client addresses; want 1", path, len(addrSeen))
398 func TestTransportMaxPerHostIdleConns(t *testing.T) {
399 defer afterTest(t)
400 resch := make(chan string)
401 gotReq := make(chan bool)
402 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
403 gotReq <- true
404 msg := <-resch
405 _, err := w.Write([]byte(msg))
406 if err != nil {
407 t.Fatalf("Write: %v", err)
410 defer ts.Close()
412 c := ts.Client()
413 tr := c.Transport.(*Transport)
414 maxIdleConnsPerHost := 2
415 tr.MaxIdleConnsPerHost = maxIdleConnsPerHost
417 // Start 3 outstanding requests and wait for the server to get them.
418 // Their responses will hang until we write to resch, though.
419 donech := make(chan bool)
420 doReq := func() {
421 resp, err := c.Get(ts.URL)
422 if err != nil {
423 t.Error(err)
424 return
426 if _, err := ioutil.ReadAll(resp.Body); err != nil {
427 t.Errorf("ReadAll: %v", err)
428 return
430 donech <- true
432 go doReq()
433 <-gotReq
434 go doReq()
435 <-gotReq
436 go doReq()
437 <-gotReq
439 if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g {
440 t.Fatalf("Before writes, expected %d idle conn cache keys; got %d", e, g)
443 resch <- "res1"
444 <-donech
445 keys := tr.IdleConnKeysForTesting()
446 if e, g := 1, len(keys); e != g {
447 t.Fatalf("after first response, expected %d idle conn cache keys; got %d", e, g)
449 addr := ts.Listener.Addr().String()
450 cacheKey := "|http|" + addr
451 if keys[0] != cacheKey {
452 t.Fatalf("Expected idle cache key %q; got %q", cacheKey, keys[0])
454 if e, g := 1, tr.IdleConnCountForTesting("http", addr); e != g {
455 t.Errorf("after first response, expected %d idle conns; got %d", e, g)
458 resch <- "res2"
459 <-donech
460 if g, w := tr.IdleConnCountForTesting("http", addr), 2; g != w {
461 t.Errorf("after second response, idle conns = %d; want %d", g, w)
464 resch <- "res3"
465 <-donech
466 if g, w := tr.IdleConnCountForTesting("http", addr), maxIdleConnsPerHost; g != w {
467 t.Errorf("after third response, idle conns = %d; want %d", g, w)
471 func TestTransportMaxConnsPerHostIncludeDialInProgress(t *testing.T) {
472 defer afterTest(t)
473 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
474 _, err := w.Write([]byte("foo"))
475 if err != nil {
476 t.Fatalf("Write: %v", err)
479 defer ts.Close()
480 c := ts.Client()
481 tr := c.Transport.(*Transport)
482 dialStarted := make(chan struct{})
483 stallDial := make(chan struct{})
484 tr.Dial = func(network, addr string) (net.Conn, error) {
485 dialStarted <- struct{}{}
486 <-stallDial
487 return net.Dial(network, addr)
490 tr.DisableKeepAlives = true
491 tr.MaxConnsPerHost = 1
493 preDial := make(chan struct{})
494 reqComplete := make(chan struct{})
495 doReq := func(reqId string) {
496 req, _ := NewRequest("GET", ts.URL, nil)
497 trace := &httptrace.ClientTrace{
498 GetConn: func(hostPort string) {
499 preDial <- struct{}{}
502 req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
503 resp, err := tr.RoundTrip(req)
504 if err != nil {
505 t.Errorf("unexpected error for request %s: %v", reqId, err)
507 _, err = ioutil.ReadAll(resp.Body)
508 if err != nil {
509 t.Errorf("unexpected error for request %s: %v", reqId, err)
511 reqComplete <- struct{}{}
513 // get req1 to dial-in-progress
514 go doReq("req1")
515 <-preDial
516 <-dialStarted
518 // get req2 to waiting on conns per host to go down below max
519 go doReq("req2")
520 <-preDial
521 select {
522 case <-dialStarted:
523 t.Error("req2 dial started while req1 dial in progress")
524 return
525 default:
528 // let req1 complete
529 stallDial <- struct{}{}
530 <-reqComplete
532 // let req2 complete
533 <-dialStarted
534 stallDial <- struct{}{}
535 <-reqComplete
538 func TestTransportRemovesDeadIdleConnections(t *testing.T) {
539 setParallel(t)
540 defer afterTest(t)
541 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
542 io.WriteString(w, r.RemoteAddr)
544 defer ts.Close()
546 c := ts.Client()
547 tr := c.Transport.(*Transport)
549 doReq := func(name string) string {
550 // Do a POST instead of a GET to prevent the Transport's
551 // idempotent request retry logic from kicking in...
552 res, err := c.Post(ts.URL, "", nil)
553 if err != nil {
554 t.Fatalf("%s: %v", name, err)
556 if res.StatusCode != 200 {
557 t.Fatalf("%s: %v", name, res.Status)
559 defer res.Body.Close()
560 slurp, err := ioutil.ReadAll(res.Body)
561 if err != nil {
562 t.Fatalf("%s: %v", name, err)
564 return string(slurp)
567 first := doReq("first")
568 keys1 := tr.IdleConnKeysForTesting()
570 ts.CloseClientConnections()
572 var keys2 []string
573 if !waitCondition(3*time.Second, 50*time.Millisecond, func() bool {
574 keys2 = tr.IdleConnKeysForTesting()
575 return len(keys2) == 0
576 }) {
577 t.Fatalf("Transport didn't notice idle connection's death.\nbefore: %q\n after: %q\n", keys1, keys2)
580 second := doReq("second")
581 if first == second {
582 t.Errorf("expected a different connection between requests. got %q both times", first)
586 func TestTransportServerClosingUnexpectedly(t *testing.T) {
587 setParallel(t)
588 defer afterTest(t)
589 ts := httptest.NewServer(hostPortHandler)
590 defer ts.Close()
591 c := ts.Client()
593 fetch := func(n, retries int) string {
594 condFatalf := func(format string, arg ...interface{}) {
595 if retries <= 0 {
596 t.Fatalf(format, arg...)
598 t.Logf("retrying shortly after expected error: "+format, arg...)
599 time.Sleep(time.Second / time.Duration(retries))
601 for retries >= 0 {
602 retries--
603 res, err := c.Get(ts.URL)
604 if err != nil {
605 condFatalf("error in req #%d, GET: %v", n, err)
606 continue
608 body, err := ioutil.ReadAll(res.Body)
609 if err != nil {
610 condFatalf("error in req #%d, ReadAll: %v", n, err)
611 continue
613 res.Body.Close()
614 return string(body)
616 panic("unreachable")
619 body1 := fetch(1, 0)
620 body2 := fetch(2, 0)
622 ts.CloseClientConnections() // surprise!
624 // This test has an expected race. Sleeping for 25 ms prevents
625 // it on most fast machines, causing the next fetch() call to
626 // succeed quickly. But if we do get errors, fetch() will retry 5
627 // times with some delays between.
628 time.Sleep(25 * time.Millisecond)
630 body3 := fetch(3, 5)
632 if body1 != body2 {
633 t.Errorf("expected body1 and body2 to be equal")
635 if body2 == body3 {
636 t.Errorf("expected body2 and body3 to be different")
640 // Test for https://golang.org/issue/2616 (appropriate issue number)
641 // This fails pretty reliably with GOMAXPROCS=100 or something high.
642 func TestStressSurpriseServerCloses(t *testing.T) {
643 defer afterTest(t)
644 if testing.Short() {
645 t.Skip("skipping test in short mode")
647 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
648 w.Header().Set("Content-Length", "5")
649 w.Header().Set("Content-Type", "text/plain")
650 w.Write([]byte("Hello"))
651 w.(Flusher).Flush()
652 conn, buf, _ := w.(Hijacker).Hijack()
653 buf.Flush()
654 conn.Close()
656 defer ts.Close()
657 c := ts.Client()
659 // Do a bunch of traffic from different goroutines. Send to activityc
660 // after each request completes, regardless of whether it failed.
661 // If these are too high, OS X exhausts its ephemeral ports
662 // and hangs waiting for them to transition TCP states. That's
663 // not what we want to test. TODO(bradfitz): use an io.Pipe
664 // dialer for this test instead?
665 const (
666 numClients = 20
667 reqsPerClient = 25
669 activityc := make(chan bool)
670 for i := 0; i < numClients; i++ {
671 go func() {
672 for i := 0; i < reqsPerClient; i++ {
673 res, err := c.Get(ts.URL)
674 if err == nil {
675 // We expect errors since the server is
676 // hanging up on us after telling us to
677 // send more requests, so we don't
678 // actually care what the error is.
679 // But we want to close the body in cases
680 // where we won the race.
681 res.Body.Close()
683 activityc <- true
688 // Make sure all the request come back, one way or another.
689 for i := 0; i < numClients*reqsPerClient; i++ {
690 select {
691 case <-activityc:
692 case <-time.After(5 * time.Second):
693 t.Fatalf("presumed deadlock; no HTTP client activity seen in awhile")
698 // TestTransportHeadResponses verifies that we deal with Content-Lengths
699 // with no bodies properly
700 func TestTransportHeadResponses(t *testing.T) {
701 defer afterTest(t)
702 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
703 if r.Method != "HEAD" {
704 panic("expected HEAD; got " + r.Method)
706 w.Header().Set("Content-Length", "123")
707 w.WriteHeader(200)
709 defer ts.Close()
710 c := ts.Client()
712 for i := 0; i < 2; i++ {
713 res, err := c.Head(ts.URL)
714 if err != nil {
715 t.Errorf("error on loop %d: %v", i, err)
716 continue
718 if e, g := "123", res.Header.Get("Content-Length"); e != g {
719 t.Errorf("loop %d: expected Content-Length header of %q, got %q", i, e, g)
721 if e, g := int64(123), res.ContentLength; e != g {
722 t.Errorf("loop %d: expected res.ContentLength of %v, got %v", i, e, g)
724 if all, err := ioutil.ReadAll(res.Body); err != nil {
725 t.Errorf("loop %d: Body ReadAll: %v", i, err)
726 } else if len(all) != 0 {
727 t.Errorf("Bogus body %q", all)
732 // TestTransportHeadChunkedResponse verifies that we ignore chunked transfer-encoding
733 // on responses to HEAD requests.
734 func TestTransportHeadChunkedResponse(t *testing.T) {
735 defer afterTest(t)
736 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
737 if r.Method != "HEAD" {
738 panic("expected HEAD; got " + r.Method)
740 w.Header().Set("Transfer-Encoding", "chunked") // client should ignore
741 w.Header().Set("x-client-ipport", r.RemoteAddr)
742 w.WriteHeader(200)
744 defer ts.Close()
745 c := ts.Client()
747 // Ensure that we wait for the readLoop to complete before
748 // calling Head again
749 didRead := make(chan bool)
750 SetReadLoopBeforeNextReadHook(func() { didRead <- true })
751 defer SetReadLoopBeforeNextReadHook(nil)
753 res1, err := c.Head(ts.URL)
754 <-didRead
756 if err != nil {
757 t.Fatalf("request 1 error: %v", err)
760 res2, err := c.Head(ts.URL)
761 <-didRead
763 if err != nil {
764 t.Fatalf("request 2 error: %v", err)
766 if v1, v2 := res1.Header.Get("x-client-ipport"), res2.Header.Get("x-client-ipport"); v1 != v2 {
767 t.Errorf("ip/ports differed between head requests: %q vs %q", v1, v2)
771 var roundTripTests = []struct {
772 accept string
773 expectAccept string
774 compressed bool
776 // Requests with no accept-encoding header use transparent compression
777 {"", "gzip", false},
778 // Requests with other accept-encoding should pass through unmodified
779 {"foo", "foo", false},
780 // Requests with accept-encoding == gzip should be passed through
781 {"gzip", "gzip", true},
784 // Test that the modification made to the Request by the RoundTripper is cleaned up
785 func TestRoundTripGzip(t *testing.T) {
786 setParallel(t)
787 defer afterTest(t)
788 const responseBody = "test response body"
789 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
790 accept := req.Header.Get("Accept-Encoding")
791 if expect := req.FormValue("expect_accept"); accept != expect {
792 t.Errorf("in handler, test %v: Accept-Encoding = %q, want %q",
793 req.FormValue("testnum"), accept, expect)
795 if accept == "gzip" {
796 rw.Header().Set("Content-Encoding", "gzip")
797 gz := gzip.NewWriter(rw)
798 gz.Write([]byte(responseBody))
799 gz.Close()
800 } else {
801 rw.Header().Set("Content-Encoding", accept)
802 rw.Write([]byte(responseBody))
805 defer ts.Close()
806 tr := ts.Client().Transport.(*Transport)
808 for i, test := range roundTripTests {
809 // Test basic request (no accept-encoding)
810 req, _ := NewRequest("GET", fmt.Sprintf("%s/?testnum=%d&expect_accept=%s", ts.URL, i, test.expectAccept), nil)
811 if test.accept != "" {
812 req.Header.Set("Accept-Encoding", test.accept)
814 res, err := tr.RoundTrip(req)
815 var body []byte
816 if test.compressed {
817 var r *gzip.Reader
818 r, err = gzip.NewReader(res.Body)
819 if err != nil {
820 t.Errorf("%d. gzip NewReader: %v", i, err)
821 continue
823 body, err = ioutil.ReadAll(r)
824 res.Body.Close()
825 } else {
826 body, err = ioutil.ReadAll(res.Body)
828 if err != nil {
829 t.Errorf("%d. Error: %q", i, err)
830 continue
832 if g, e := string(body), responseBody; g != e {
833 t.Errorf("%d. body = %q; want %q", i, g, e)
835 if g, e := req.Header.Get("Accept-Encoding"), test.accept; g != e {
836 t.Errorf("%d. Accept-Encoding = %q; want %q (it was mutated, in violation of RoundTrip contract)", i, g, e)
838 if g, e := res.Header.Get("Content-Encoding"), test.accept; g != e {
839 t.Errorf("%d. Content-Encoding = %q; want %q", i, g, e)
845 func TestTransportGzip(t *testing.T) {
846 setParallel(t)
847 defer afterTest(t)
848 const testString = "The test string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
849 const nRandBytes = 1024 * 1024
850 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
851 if req.Method == "HEAD" {
852 if g := req.Header.Get("Accept-Encoding"); g != "" {
853 t.Errorf("HEAD request sent with Accept-Encoding of %q; want none", g)
855 return
857 if g, e := req.Header.Get("Accept-Encoding"), "gzip"; g != e {
858 t.Errorf("Accept-Encoding = %q, want %q", g, e)
860 rw.Header().Set("Content-Encoding", "gzip")
862 var w io.Writer = rw
863 var buf bytes.Buffer
864 if req.FormValue("chunked") == "0" {
865 w = &buf
866 defer io.Copy(rw, &buf)
867 defer func() {
868 rw.Header().Set("Content-Length", strconv.Itoa(buf.Len()))
871 gz := gzip.NewWriter(w)
872 gz.Write([]byte(testString))
873 if req.FormValue("body") == "large" {
874 io.CopyN(gz, rand.Reader, nRandBytes)
876 gz.Close()
878 defer ts.Close()
879 c := ts.Client()
881 for _, chunked := range []string{"1", "0"} {
882 // First fetch something large, but only read some of it.
883 res, err := c.Get(ts.URL + "/?body=large&chunked=" + chunked)
884 if err != nil {
885 t.Fatalf("large get: %v", err)
887 buf := make([]byte, len(testString))
888 n, err := io.ReadFull(res.Body, buf)
889 if err != nil {
890 t.Fatalf("partial read of large response: size=%d, %v", n, err)
892 if e, g := testString, string(buf); e != g {
893 t.Errorf("partial read got %q, expected %q", g, e)
895 res.Body.Close()
896 // Read on the body, even though it's closed
897 n, err = res.Body.Read(buf)
898 if n != 0 || err == nil {
899 t.Errorf("expected error post-closed large Read; got = %d, %v", n, err)
902 // Then something small.
903 res, err = c.Get(ts.URL + "/?chunked=" + chunked)
904 if err != nil {
905 t.Fatal(err)
907 body, err := ioutil.ReadAll(res.Body)
908 if err != nil {
909 t.Fatal(err)
911 if g, e := string(body), testString; g != e {
912 t.Fatalf("body = %q; want %q", g, e)
914 if g, e := res.Header.Get("Content-Encoding"), ""; g != e {
915 t.Fatalf("Content-Encoding = %q; want %q", g, e)
918 // Read on the body after it's been fully read:
919 n, err = res.Body.Read(buf)
920 if n != 0 || err == nil {
921 t.Errorf("expected Read error after exhausted reads; got %d, %v", n, err)
923 res.Body.Close()
924 n, err = res.Body.Read(buf)
925 if n != 0 || err == nil {
926 t.Errorf("expected Read error after Close; got %d, %v", n, err)
930 // And a HEAD request too, because they're always weird.
931 res, err := c.Head(ts.URL)
932 if err != nil {
933 t.Fatalf("Head: %v", err)
935 if res.StatusCode != 200 {
936 t.Errorf("Head status=%d; want=200", res.StatusCode)
940 // If a request has Expect:100-continue header, the request blocks sending body until the first response.
941 // Premature consumption of the request body should not be occurred.
942 func TestTransportExpect100Continue(t *testing.T) {
943 setParallel(t)
944 defer afterTest(t)
946 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
947 switch req.URL.Path {
948 case "/100":
949 // This endpoint implicitly responds 100 Continue and reads body.
950 if _, err := io.Copy(ioutil.Discard, req.Body); err != nil {
951 t.Error("Failed to read Body", err)
953 rw.WriteHeader(StatusOK)
954 case "/200":
955 // Go 1.5 adds Connection: close header if the client expect
956 // continue but not entire request body is consumed.
957 rw.WriteHeader(StatusOK)
958 case "/500":
959 rw.WriteHeader(StatusInternalServerError)
960 case "/keepalive":
961 // This hijacked endpoint responds error without Connection:close.
962 _, bufrw, err := rw.(Hijacker).Hijack()
963 if err != nil {
964 log.Fatal(err)
966 bufrw.WriteString("HTTP/1.1 500 Internal Server Error\r\n")
967 bufrw.WriteString("Content-Length: 0\r\n\r\n")
968 bufrw.Flush()
969 case "/timeout":
970 // This endpoint tries to read body without 100 (Continue) response.
971 // After ExpectContinueTimeout, the reading will be started.
972 conn, bufrw, err := rw.(Hijacker).Hijack()
973 if err != nil {
974 log.Fatal(err)
976 if _, err := io.CopyN(ioutil.Discard, bufrw, req.ContentLength); err != nil {
977 t.Error("Failed to read Body", err)
979 bufrw.WriteString("HTTP/1.1 200 OK\r\n\r\n")
980 bufrw.Flush()
981 conn.Close()
985 defer ts.Close()
987 tests := []struct {
988 path string
989 body []byte
990 sent int
991 status int
993 {path: "/100", body: []byte("hello"), sent: 5, status: 200}, // Got 100 followed by 200, entire body is sent.
994 {path: "/200", body: []byte("hello"), sent: 0, status: 200}, // Got 200 without 100. body isn't sent.
995 {path: "/500", body: []byte("hello"), sent: 0, status: 500}, // Got 500 without 100. body isn't sent.
996 {path: "/keepalive", body: []byte("hello"), sent: 0, status: 500}, // Although without Connection:close, body isn't sent.
997 {path: "/timeout", body: []byte("hello"), sent: 5, status: 200}, // Timeout exceeded and entire body is sent.
1000 c := ts.Client()
1001 for i, v := range tests {
1002 tr := &Transport{
1003 ExpectContinueTimeout: 2 * time.Second,
1005 defer tr.CloseIdleConnections()
1006 c.Transport = tr
1007 body := bytes.NewReader(v.body)
1008 req, err := NewRequest("PUT", ts.URL+v.path, body)
1009 if err != nil {
1010 t.Fatal(err)
1012 req.Header.Set("Expect", "100-continue")
1013 req.ContentLength = int64(len(v.body))
1015 resp, err := c.Do(req)
1016 if err != nil {
1017 t.Fatal(err)
1019 resp.Body.Close()
1021 sent := len(v.body) - body.Len()
1022 if v.status != resp.StatusCode {
1023 t.Errorf("test %d: status code should be %d but got %d. (%s)", i, v.status, resp.StatusCode, v.path)
1025 if v.sent != sent {
1026 t.Errorf("test %d: sent body should be %d but sent %d. (%s)", i, v.sent, sent, v.path)
1031 func TestSOCKS5Proxy(t *testing.T) {
1032 defer afterTest(t)
1033 ch := make(chan string, 1)
1034 l := newLocalListener(t)
1035 defer l.Close()
1036 defer close(ch)
1037 proxy := func(t *testing.T) {
1038 s, err := l.Accept()
1039 if err != nil {
1040 t.Errorf("socks5 proxy Accept(): %v", err)
1041 return
1043 defer s.Close()
1044 var buf [22]byte
1045 if _, err := io.ReadFull(s, buf[:3]); err != nil {
1046 t.Errorf("socks5 proxy initial read: %v", err)
1047 return
1049 if want := []byte{5, 1, 0}; !bytes.Equal(buf[:3], want) {
1050 t.Errorf("socks5 proxy initial read: got %v, want %v", buf[:3], want)
1051 return
1053 if _, err := s.Write([]byte{5, 0}); err != nil {
1054 t.Errorf("socks5 proxy initial write: %v", err)
1055 return
1057 if _, err := io.ReadFull(s, buf[:4]); err != nil {
1058 t.Errorf("socks5 proxy second read: %v", err)
1059 return
1061 if want := []byte{5, 1, 0}; !bytes.Equal(buf[:3], want) {
1062 t.Errorf("socks5 proxy second read: got %v, want %v", buf[:3], want)
1063 return
1065 var ipLen int
1066 switch buf[3] {
1067 case 1:
1068 ipLen = net.IPv4len
1069 case 4:
1070 ipLen = net.IPv6len
1071 default:
1072 t.Errorf("socks5 proxy second read: unexpected address type %v", buf[4])
1073 return
1075 if _, err := io.ReadFull(s, buf[4:ipLen+6]); err != nil {
1076 t.Errorf("socks5 proxy address read: %v", err)
1077 return
1079 ip := net.IP(buf[4 : ipLen+4])
1080 port := binary.BigEndian.Uint16(buf[ipLen+4 : ipLen+6])
1081 copy(buf[:3], []byte{5, 0, 0})
1082 if _, err := s.Write(buf[:ipLen+6]); err != nil {
1083 t.Errorf("socks5 proxy connect write: %v", err)
1084 return
1086 ch <- fmt.Sprintf("proxy for %s:%d", ip, port)
1088 // Implement proxying.
1089 targetHost := net.JoinHostPort(ip.String(), strconv.Itoa(int(port)))
1090 targetConn, err := net.Dial("tcp", targetHost)
1091 if err != nil {
1092 t.Errorf("net.Dial failed")
1093 return
1095 go io.Copy(targetConn, s)
1096 io.Copy(s, targetConn) // Wait for the client to close the socket.
1097 targetConn.Close()
1100 pu, err := url.Parse("socks5://" + l.Addr().String())
1101 if err != nil {
1102 t.Fatal(err)
1105 sentinelHeader := "X-Sentinel"
1106 sentinelValue := "12345"
1107 h := HandlerFunc(func(w ResponseWriter, r *Request) {
1108 w.Header().Set(sentinelHeader, sentinelValue)
1110 for _, useTLS := range []bool{false, true} {
1111 t.Run(fmt.Sprintf("useTLS=%v", useTLS), func(t *testing.T) {
1112 var ts *httptest.Server
1113 if useTLS {
1114 ts = httptest.NewTLSServer(h)
1115 } else {
1116 ts = httptest.NewServer(h)
1118 go proxy(t)
1119 c := ts.Client()
1120 c.Transport.(*Transport).Proxy = ProxyURL(pu)
1121 r, err := c.Head(ts.URL)
1122 if err != nil {
1123 t.Fatal(err)
1125 if r.Header.Get(sentinelHeader) != sentinelValue {
1126 t.Errorf("Failed to retrieve sentinel value")
1128 var got string
1129 select {
1130 case got = <-ch:
1131 case <-time.After(5 * time.Second):
1132 t.Fatal("timeout connecting to socks5 proxy")
1134 ts.Close()
1135 tsu, err := url.Parse(ts.URL)
1136 if err != nil {
1137 t.Fatal(err)
1139 want := "proxy for " + tsu.Host
1140 if got != want {
1141 t.Errorf("got %q, want %q", got, want)
1147 func TestTransportProxy(t *testing.T) {
1148 defer afterTest(t)
1149 testCases := []struct{ httpsSite, httpsProxy bool }{
1150 {false, false},
1151 {false, true},
1152 {true, false},
1153 {true, true},
1155 for _, testCase := range testCases {
1156 httpsSite := testCase.httpsSite
1157 httpsProxy := testCase.httpsProxy
1158 t.Run(fmt.Sprintf("httpsSite=%v, httpsProxy=%v", httpsSite, httpsProxy), func(t *testing.T) {
1159 siteCh := make(chan *Request, 1)
1160 h1 := HandlerFunc(func(w ResponseWriter, r *Request) {
1161 siteCh <- r
1163 proxyCh := make(chan *Request, 1)
1164 h2 := HandlerFunc(func(w ResponseWriter, r *Request) {
1165 proxyCh <- r
1166 // Implement an entire CONNECT proxy
1167 if r.Method == "CONNECT" {
1168 hijacker, ok := w.(Hijacker)
1169 if !ok {
1170 t.Errorf("hijack not allowed")
1171 return
1173 clientConn, _, err := hijacker.Hijack()
1174 if err != nil {
1175 t.Errorf("hijacking failed")
1176 return
1178 res := &Response{
1179 StatusCode: StatusOK,
1180 Proto: "HTTP/1.1",
1181 ProtoMajor: 1,
1182 ProtoMinor: 1,
1183 Header: make(Header),
1186 targetConn, err := net.Dial("tcp", r.URL.Host)
1187 if err != nil {
1188 t.Errorf("net.Dial(%q) failed: %v", r.URL.Host, err)
1189 return
1192 if err := res.Write(clientConn); err != nil {
1193 t.Errorf("Writing 200 OK failed: %v", err)
1194 return
1197 go io.Copy(targetConn, clientConn)
1198 go func() {
1199 io.Copy(clientConn, targetConn)
1200 targetConn.Close()
1204 var ts *httptest.Server
1205 if httpsSite {
1206 ts = httptest.NewTLSServer(h1)
1207 } else {
1208 ts = httptest.NewServer(h1)
1210 var proxy *httptest.Server
1211 if httpsProxy {
1212 proxy = httptest.NewTLSServer(h2)
1213 } else {
1214 proxy = httptest.NewServer(h2)
1217 pu, err := url.Parse(proxy.URL)
1218 if err != nil {
1219 t.Fatal(err)
1222 // If neither server is HTTPS or both are, then c may be derived from either.
1223 // If only one server is HTTPS, c must be derived from that server in order
1224 // to ensure that it is configured to use the fake root CA from testcert.go.
1225 c := proxy.Client()
1226 if httpsSite {
1227 c = ts.Client()
1230 c.Transport.(*Transport).Proxy = ProxyURL(pu)
1231 if _, err := c.Head(ts.URL); err != nil {
1232 t.Error(err)
1234 var got *Request
1235 select {
1236 case got = <-proxyCh:
1237 case <-time.After(5 * time.Second):
1238 t.Fatal("timeout connecting to http proxy")
1240 c.Transport.(*Transport).CloseIdleConnections()
1241 ts.Close()
1242 proxy.Close()
1243 if httpsSite {
1244 // First message should be a CONNECT, asking for a socket to the real server,
1245 if got.Method != "CONNECT" {
1246 t.Errorf("Wrong method for secure proxying: %q", got.Method)
1248 gotHost := got.URL.Host
1249 pu, err := url.Parse(ts.URL)
1250 if err != nil {
1251 t.Fatal("Invalid site URL")
1253 if wantHost := pu.Host; gotHost != wantHost {
1254 t.Errorf("Got CONNECT host %q, want %q", gotHost, wantHost)
1257 // The next message on the channel should be from the site's server.
1258 next := <-siteCh
1259 if next.Method != "HEAD" {
1260 t.Errorf("Wrong method at destination: %s", next.Method)
1262 if nextURL := next.URL.String(); nextURL != "/" {
1263 t.Errorf("Wrong URL at destination: %s", nextURL)
1265 } else {
1266 if got.Method != "HEAD" {
1267 t.Errorf("Wrong method for destination: %q", got.Method)
1269 gotURL := got.URL.String()
1270 wantURL := ts.URL + "/"
1271 if gotURL != wantURL {
1272 t.Errorf("Got URL %q, want %q", gotURL, wantURL)
1279 // Issue 16997: test transport dial preserves typed errors
1280 func TestTransportDialPreservesNetOpProxyError(t *testing.T) {
1281 defer afterTest(t)
1283 var errDial = errors.New("some dial error")
1285 tr := &Transport{
1286 Proxy: func(*Request) (*url.URL, error) {
1287 return url.Parse("http://proxy.fake.tld/")
1289 Dial: func(string, string) (net.Conn, error) {
1290 return nil, errDial
1293 defer tr.CloseIdleConnections()
1295 c := &Client{Transport: tr}
1296 req, _ := NewRequest("GET", "http://fake.tld", nil)
1297 res, err := c.Do(req)
1298 if err == nil {
1299 res.Body.Close()
1300 t.Fatal("wanted a non-nil error")
1303 uerr, ok := err.(*url.Error)
1304 if !ok {
1305 t.Fatalf("got %T, want *url.Error", err)
1307 oe, ok := uerr.Err.(*net.OpError)
1308 if !ok {
1309 t.Fatalf("url.Error.Err = %T; want *net.OpError", uerr.Err)
1311 want := &net.OpError{
1312 Op: "proxyconnect",
1313 Net: "tcp",
1314 Err: errDial, // original error, unwrapped.
1316 if !reflect.DeepEqual(oe, want) {
1317 t.Errorf("Got error %#v; want %#v", oe, want)
1321 // TestTransportGzipRecursive sends a gzip quine and checks that the
1322 // client gets the same value back. This is more cute than anything,
1323 // but checks that we don't recurse forever, and checks that
1324 // Content-Encoding is removed.
1325 func TestTransportGzipRecursive(t *testing.T) {
1326 defer afterTest(t)
1327 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
1328 w.Header().Set("Content-Encoding", "gzip")
1329 w.Write(rgz)
1331 defer ts.Close()
1333 c := ts.Client()
1334 res, err := c.Get(ts.URL)
1335 if err != nil {
1336 t.Fatal(err)
1338 body, err := ioutil.ReadAll(res.Body)
1339 if err != nil {
1340 t.Fatal(err)
1342 if !bytes.Equal(body, rgz) {
1343 t.Fatalf("Incorrect result from recursive gz:\nhave=%x\nwant=%x",
1344 body, rgz)
1346 if g, e := res.Header.Get("Content-Encoding"), ""; g != e {
1347 t.Fatalf("Content-Encoding = %q; want %q", g, e)
1351 // golang.org/issue/7750: request fails when server replies with
1352 // a short gzip body
1353 func TestTransportGzipShort(t *testing.T) {
1354 defer afterTest(t)
1355 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
1356 w.Header().Set("Content-Encoding", "gzip")
1357 w.Write([]byte{0x1f, 0x8b})
1359 defer ts.Close()
1361 c := ts.Client()
1362 res, err := c.Get(ts.URL)
1363 if err != nil {
1364 t.Fatal(err)
1366 defer res.Body.Close()
1367 _, err = ioutil.ReadAll(res.Body)
1368 if err == nil {
1369 t.Fatal("Expect an error from reading a body.")
1371 if err != io.ErrUnexpectedEOF {
1372 t.Errorf("ReadAll error = %v; want io.ErrUnexpectedEOF", err)
1376 // Wait until number of goroutines is no greater than nmax, or time out.
1377 func waitNumGoroutine(nmax int) int {
1378 nfinal := runtime.NumGoroutine()
1379 for ntries := 10; ntries > 0 && nfinal > nmax; ntries-- {
1380 time.Sleep(50 * time.Millisecond)
1381 runtime.GC()
1382 nfinal = runtime.NumGoroutine()
1384 return nfinal
1387 // tests that persistent goroutine connections shut down when no longer desired.
1388 func TestTransportPersistConnLeak(t *testing.T) {
1389 // Not parallel: counts goroutines
1390 defer afterTest(t)
1392 const numReq = 25
1393 gotReqCh := make(chan bool, numReq)
1394 unblockCh := make(chan bool, numReq)
1395 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
1396 gotReqCh <- true
1397 <-unblockCh
1398 w.Header().Set("Content-Length", "0")
1399 w.WriteHeader(204)
1401 defer ts.Close()
1402 c := ts.Client()
1403 tr := c.Transport.(*Transport)
1405 n0 := runtime.NumGoroutine()
1407 didReqCh := make(chan bool, numReq)
1408 failed := make(chan bool, numReq)
1409 for i := 0; i < numReq; i++ {
1410 go func() {
1411 res, err := c.Get(ts.URL)
1412 didReqCh <- true
1413 if err != nil {
1414 t.Errorf("client fetch error: %v", err)
1415 failed <- true
1416 return
1418 res.Body.Close()
1422 // Wait for all goroutines to be stuck in the Handler.
1423 for i := 0; i < numReq; i++ {
1424 select {
1425 case <-gotReqCh:
1426 // ok
1427 case <-failed:
1428 close(unblockCh)
1429 return
1433 nhigh := runtime.NumGoroutine()
1435 // Tell all handlers to unblock and reply.
1436 for i := 0; i < numReq; i++ {
1437 unblockCh <- true
1440 // Wait for all HTTP clients to be done.
1441 for i := 0; i < numReq; i++ {
1442 <-didReqCh
1445 tr.CloseIdleConnections()
1446 nfinal := waitNumGoroutine(n0 + 5)
1448 growth := nfinal - n0
1450 // We expect 0 or 1 extra goroutine, empirically. Allow up to 5.
1451 // Previously we were leaking one per numReq.
1452 if int(growth) > 5 {
1453 t.Logf("goroutine growth: %d -> %d -> %d (delta: %d)", n0, nhigh, nfinal, growth)
1454 t.Error("too many new goroutines")
1458 // golang.org/issue/4531: Transport leaks goroutines when
1459 // request.ContentLength is explicitly short
1460 func TestTransportPersistConnLeakShortBody(t *testing.T) {
1461 // Not parallel: measures goroutines.
1462 defer afterTest(t)
1463 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
1465 defer ts.Close()
1466 c := ts.Client()
1467 tr := c.Transport.(*Transport)
1469 n0 := runtime.NumGoroutine()
1470 body := []byte("Hello")
1471 for i := 0; i < 20; i++ {
1472 req, err := NewRequest("POST", ts.URL, bytes.NewReader(body))
1473 if err != nil {
1474 t.Fatal(err)
1476 req.ContentLength = int64(len(body) - 2) // explicitly short
1477 _, err = c.Do(req)
1478 if err == nil {
1479 t.Fatal("Expect an error from writing too long of a body.")
1482 nhigh := runtime.NumGoroutine()
1483 tr.CloseIdleConnections()
1484 nfinal := waitNumGoroutine(n0 + 5)
1486 growth := nfinal - n0
1488 // We expect 0 or 1 extra goroutine, empirically. Allow up to 5.
1489 // Previously we were leaking one per numReq.
1490 t.Logf("goroutine growth: %d -> %d -> %d (delta: %d)", n0, nhigh, nfinal, growth)
1491 if int(growth) > 5 {
1492 t.Error("too many new goroutines")
1496 // This used to crash; https://golang.org/issue/3266
1497 func TestTransportIdleConnCrash(t *testing.T) {
1498 defer afterTest(t)
1499 var tr *Transport
1501 unblockCh := make(chan bool, 1)
1502 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
1503 <-unblockCh
1504 tr.CloseIdleConnections()
1506 defer ts.Close()
1507 c := ts.Client()
1508 tr = c.Transport.(*Transport)
1510 didreq := make(chan bool)
1511 go func() {
1512 res, err := c.Get(ts.URL)
1513 if err != nil {
1514 t.Error(err)
1515 } else {
1516 res.Body.Close() // returns idle conn
1518 didreq <- true
1520 unblockCh <- true
1521 <-didreq
1524 // Test that the transport doesn't close the TCP connection early,
1525 // before the response body has been read. This was a regression
1526 // which sadly lacked a triggering test. The large response body made
1527 // the old race easier to trigger.
1528 func TestIssue3644(t *testing.T) {
1529 defer afterTest(t)
1530 const numFoos = 5000
1531 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
1532 w.Header().Set("Connection", "close")
1533 for i := 0; i < numFoos; i++ {
1534 w.Write([]byte("foo "))
1537 defer ts.Close()
1538 c := ts.Client()
1539 res, err := c.Get(ts.URL)
1540 if err != nil {
1541 t.Fatal(err)
1543 defer res.Body.Close()
1544 bs, err := ioutil.ReadAll(res.Body)
1545 if err != nil {
1546 t.Fatal(err)
1548 if len(bs) != numFoos*len("foo ") {
1549 t.Errorf("unexpected response length")
1553 // Test that a client receives a server's reply, even if the server doesn't read
1554 // the entire request body.
1555 func TestIssue3595(t *testing.T) {
1556 setParallel(t)
1557 defer afterTest(t)
1558 const deniedMsg = "sorry, denied."
1559 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
1560 Error(w, deniedMsg, StatusUnauthorized)
1562 defer ts.Close()
1563 c := ts.Client()
1564 res, err := c.Post(ts.URL, "application/octet-stream", neverEnding('a'))
1565 if err != nil {
1566 t.Errorf("Post: %v", err)
1567 return
1569 got, err := ioutil.ReadAll(res.Body)
1570 if err != nil {
1571 t.Fatalf("Body ReadAll: %v", err)
1573 if !strings.Contains(string(got), deniedMsg) {
1574 t.Errorf("Known bug: response %q does not contain %q", got, deniedMsg)
1578 // From https://golang.org/issue/4454 ,
1579 // "client fails to handle requests with no body and chunked encoding"
1580 func TestChunkedNoContent(t *testing.T) {
1581 defer afterTest(t)
1582 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
1583 w.WriteHeader(StatusNoContent)
1585 defer ts.Close()
1587 c := ts.Client()
1588 for _, closeBody := range []bool{true, false} {
1589 const n = 4
1590 for i := 1; i <= n; i++ {
1591 res, err := c.Get(ts.URL)
1592 if err != nil {
1593 t.Errorf("closingBody=%v, req %d/%d: %v", closeBody, i, n, err)
1594 } else {
1595 if closeBody {
1596 res.Body.Close()
1603 func TestTransportConcurrency(t *testing.T) {
1604 // Not parallel: uses global test hooks.
1605 defer afterTest(t)
1606 maxProcs, numReqs := 16, 500
1607 if testing.Short() {
1608 maxProcs, numReqs = 4, 50
1610 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs))
1611 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
1612 fmt.Fprintf(w, "%v", r.FormValue("echo"))
1614 defer ts.Close()
1616 var wg sync.WaitGroup
1617 wg.Add(numReqs)
1619 // Due to the Transport's "socket late binding" (see
1620 // idleConnCh in transport.go), the numReqs HTTP requests
1621 // below can finish with a dial still outstanding. To keep
1622 // the leak checker happy, keep track of pending dials and
1623 // wait for them to finish (and be closed or returned to the
1624 // idle pool) before we close idle connections.
1625 SetPendingDialHooks(func() { wg.Add(1) }, wg.Done)
1626 defer SetPendingDialHooks(nil, nil)
1628 c := ts.Client()
1629 reqs := make(chan string)
1630 defer close(reqs)
1632 for i := 0; i < maxProcs*2; i++ {
1633 go func() {
1634 for req := range reqs {
1635 res, err := c.Get(ts.URL + "/?echo=" + req)
1636 if err != nil {
1637 t.Errorf("error on req %s: %v", req, err)
1638 wg.Done()
1639 continue
1641 all, err := ioutil.ReadAll(res.Body)
1642 if err != nil {
1643 t.Errorf("read error on req %s: %v", req, err)
1644 wg.Done()
1645 continue
1647 if string(all) != req {
1648 t.Errorf("body of req %s = %q; want %q", req, all, req)
1650 res.Body.Close()
1651 wg.Done()
1655 for i := 0; i < numReqs; i++ {
1656 reqs <- fmt.Sprintf("request-%d", i)
1658 wg.Wait()
1661 func TestIssue4191_InfiniteGetTimeout(t *testing.T) {
1662 setParallel(t)
1663 defer afterTest(t)
1664 const debug = false
1665 mux := NewServeMux()
1666 mux.HandleFunc("/get", func(w ResponseWriter, r *Request) {
1667 io.Copy(w, neverEnding('a'))
1669 ts := httptest.NewServer(mux)
1670 defer ts.Close()
1671 timeout := 100 * time.Millisecond
1673 c := ts.Client()
1674 c.Transport.(*Transport).Dial = func(n, addr string) (net.Conn, error) {
1675 conn, err := net.Dial(n, addr)
1676 if err != nil {
1677 return nil, err
1679 conn.SetDeadline(time.Now().Add(timeout))
1680 if debug {
1681 conn = NewLoggingConn("client", conn)
1683 return conn, nil
1686 getFailed := false
1687 nRuns := 5
1688 if testing.Short() {
1689 nRuns = 1
1691 for i := 0; i < nRuns; i++ {
1692 if debug {
1693 println("run", i+1, "of", nRuns)
1695 sres, err := c.Get(ts.URL + "/get")
1696 if err != nil {
1697 if !getFailed {
1698 // Make the timeout longer, once.
1699 getFailed = true
1700 t.Logf("increasing timeout")
1702 timeout *= 10
1703 continue
1705 t.Errorf("Error issuing GET: %v", err)
1706 break
1708 _, err = io.Copy(ioutil.Discard, sres.Body)
1709 if err == nil {
1710 t.Errorf("Unexpected successful copy")
1711 break
1714 if debug {
1715 println("tests complete; waiting for handlers to finish")
1719 func TestIssue4191_InfiniteGetToPutTimeout(t *testing.T) {
1720 setParallel(t)
1721 defer afterTest(t)
1722 const debug = false
1723 mux := NewServeMux()
1724 mux.HandleFunc("/get", func(w ResponseWriter, r *Request) {
1725 io.Copy(w, neverEnding('a'))
1727 mux.HandleFunc("/put", func(w ResponseWriter, r *Request) {
1728 defer r.Body.Close()
1729 io.Copy(ioutil.Discard, r.Body)
1731 ts := httptest.NewServer(mux)
1732 timeout := 100 * time.Millisecond
1734 c := ts.Client()
1735 c.Transport.(*Transport).Dial = func(n, addr string) (net.Conn, error) {
1736 conn, err := net.Dial(n, addr)
1737 if err != nil {
1738 return nil, err
1740 conn.SetDeadline(time.Now().Add(timeout))
1741 if debug {
1742 conn = NewLoggingConn("client", conn)
1744 return conn, nil
1747 getFailed := false
1748 nRuns := 5
1749 if testing.Short() {
1750 nRuns = 1
1752 for i := 0; i < nRuns; i++ {
1753 if debug {
1754 println("run", i+1, "of", nRuns)
1756 sres, err := c.Get(ts.URL + "/get")
1757 if err != nil {
1758 if !getFailed {
1759 // Make the timeout longer, once.
1760 getFailed = true
1761 t.Logf("increasing timeout")
1763 timeout *= 10
1764 continue
1766 t.Errorf("Error issuing GET: %v", err)
1767 break
1769 req, _ := NewRequest("PUT", ts.URL+"/put", sres.Body)
1770 _, err = c.Do(req)
1771 if err == nil {
1772 sres.Body.Close()
1773 t.Errorf("Unexpected successful PUT")
1774 break
1776 sres.Body.Close()
1778 if debug {
1779 println("tests complete; waiting for handlers to finish")
1781 ts.Close()
1784 func TestTransportResponseHeaderTimeout(t *testing.T) {
1785 setParallel(t)
1786 defer afterTest(t)
1787 if testing.Short() {
1788 t.Skip("skipping timeout test in -short mode")
1790 inHandler := make(chan bool, 1)
1791 mux := NewServeMux()
1792 mux.HandleFunc("/fast", func(w ResponseWriter, r *Request) {
1793 inHandler <- true
1795 mux.HandleFunc("/slow", func(w ResponseWriter, r *Request) {
1796 inHandler <- true
1797 time.Sleep(2 * time.Second)
1799 ts := httptest.NewServer(mux)
1800 defer ts.Close()
1802 c := ts.Client()
1803 c.Transport.(*Transport).ResponseHeaderTimeout = 500 * time.Millisecond
1805 tests := []struct {
1806 path string
1807 want int
1808 wantErr string
1810 {path: "/fast", want: 200},
1811 {path: "/slow", wantErr: "timeout awaiting response headers"},
1812 {path: "/fast", want: 200},
1814 for i, tt := range tests {
1815 req, _ := NewRequest("GET", ts.URL+tt.path, nil)
1816 req = req.WithT(t)
1817 res, err := c.Do(req)
1818 select {
1819 case <-inHandler:
1820 case <-time.After(5 * time.Second):
1821 t.Errorf("never entered handler for test index %d, %s", i, tt.path)
1822 continue
1824 if err != nil {
1825 uerr, ok := err.(*url.Error)
1826 if !ok {
1827 t.Errorf("error is not an url.Error; got: %#v", err)
1828 continue
1830 nerr, ok := uerr.Err.(net.Error)
1831 if !ok {
1832 t.Errorf("error does not satisfy net.Error interface; got: %#v", err)
1833 continue
1835 if !nerr.Timeout() {
1836 t.Errorf("want timeout error; got: %q", nerr)
1837 continue
1839 if strings.Contains(err.Error(), tt.wantErr) {
1840 continue
1842 t.Errorf("%d. unexpected error: %v", i, err)
1843 continue
1845 if tt.wantErr != "" {
1846 t.Errorf("%d. no error. expected error: %v", i, tt.wantErr)
1847 continue
1849 if res.StatusCode != tt.want {
1850 t.Errorf("%d for path %q status = %d; want %d", i, tt.path, res.StatusCode, tt.want)
1855 func TestTransportCancelRequest(t *testing.T) {
1856 setParallel(t)
1857 defer afterTest(t)
1858 if testing.Short() {
1859 t.Skip("skipping test in -short mode")
1861 unblockc := make(chan bool)
1862 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
1863 fmt.Fprintf(w, "Hello")
1864 w.(Flusher).Flush() // send headers and some body
1865 <-unblockc
1867 defer ts.Close()
1868 defer close(unblockc)
1870 c := ts.Client()
1871 tr := c.Transport.(*Transport)
1873 req, _ := NewRequest("GET", ts.URL, nil)
1874 res, err := c.Do(req)
1875 if err != nil {
1876 t.Fatal(err)
1878 go func() {
1879 time.Sleep(1 * time.Second)
1880 tr.CancelRequest(req)
1882 t0 := time.Now()
1883 body, err := ioutil.ReadAll(res.Body)
1884 d := time.Since(t0)
1886 if err != ExportErrRequestCanceled {
1887 t.Errorf("Body.Read error = %v; want errRequestCanceled", err)
1889 if string(body) != "Hello" {
1890 t.Errorf("Body = %q; want Hello", body)
1892 if d < 500*time.Millisecond {
1893 t.Errorf("expected ~1 second delay; got %v", d)
1895 // Verify no outstanding requests after readLoop/writeLoop
1896 // goroutines shut down.
1897 for tries := 5; tries > 0; tries-- {
1898 n := tr.NumPendingRequestsForTesting()
1899 if n == 0 {
1900 break
1902 time.Sleep(100 * time.Millisecond)
1903 if tries == 1 {
1904 t.Errorf("pending requests = %d; want 0", n)
1909 func TestTransportCancelRequestInDial(t *testing.T) {
1910 defer afterTest(t)
1911 if testing.Short() {
1912 t.Skip("skipping test in -short mode")
1914 var logbuf bytes.Buffer
1915 eventLog := log.New(&logbuf, "", 0)
1917 unblockDial := make(chan bool)
1918 defer close(unblockDial)
1920 inDial := make(chan bool)
1921 tr := &Transport{
1922 Dial: func(network, addr string) (net.Conn, error) {
1923 eventLog.Println("dial: blocking")
1924 inDial <- true
1925 <-unblockDial
1926 return nil, errors.New("nope")
1929 cl := &Client{Transport: tr}
1930 gotres := make(chan bool)
1931 req, _ := NewRequest("GET", "http://something.no-network.tld/", nil)
1932 go func() {
1933 _, err := cl.Do(req)
1934 eventLog.Printf("Get = %v", err)
1935 gotres <- true
1938 select {
1939 case <-inDial:
1940 case <-time.After(5 * time.Second):
1941 t.Fatal("timeout; never saw blocking dial")
1944 eventLog.Printf("canceling")
1945 tr.CancelRequest(req)
1946 tr.CancelRequest(req) // used to panic on second call
1948 select {
1949 case <-gotres:
1950 case <-time.After(5 * time.Second):
1951 panic("hang. events are: " + logbuf.String())
1954 got := logbuf.String()
1955 want := `dial: blocking
1956 canceling
1957 Get = Get http://something.no-network.tld/: net/http: request canceled while waiting for connection
1959 if got != want {
1960 t.Errorf("Got events:\n%s\nWant:\n%s", got, want)
1964 func TestCancelRequestWithChannel(t *testing.T) {
1965 setParallel(t)
1966 defer afterTest(t)
1967 if testing.Short() {
1968 t.Skip("skipping test in -short mode")
1970 unblockc := make(chan bool)
1971 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
1972 fmt.Fprintf(w, "Hello")
1973 w.(Flusher).Flush() // send headers and some body
1974 <-unblockc
1976 defer ts.Close()
1977 defer close(unblockc)
1979 c := ts.Client()
1980 tr := c.Transport.(*Transport)
1982 req, _ := NewRequest("GET", ts.URL, nil)
1983 ch := make(chan struct{})
1984 req.Cancel = ch
1986 res, err := c.Do(req)
1987 if err != nil {
1988 t.Fatal(err)
1990 go func() {
1991 time.Sleep(1 * time.Second)
1992 close(ch)
1994 t0 := time.Now()
1995 body, err := ioutil.ReadAll(res.Body)
1996 d := time.Since(t0)
1998 if err != ExportErrRequestCanceled {
1999 t.Errorf("Body.Read error = %v; want errRequestCanceled", err)
2001 if string(body) != "Hello" {
2002 t.Errorf("Body = %q; want Hello", body)
2004 if d < 500*time.Millisecond {
2005 t.Errorf("expected ~1 second delay; got %v", d)
2007 // Verify no outstanding requests after readLoop/writeLoop
2008 // goroutines shut down.
2009 for tries := 5; tries > 0; tries-- {
2010 n := tr.NumPendingRequestsForTesting()
2011 if n == 0 {
2012 break
2014 time.Sleep(100 * time.Millisecond)
2015 if tries == 1 {
2016 t.Errorf("pending requests = %d; want 0", n)
2021 func TestCancelRequestWithChannelBeforeDo_Cancel(t *testing.T) {
2022 testCancelRequestWithChannelBeforeDo(t, false)
2024 func TestCancelRequestWithChannelBeforeDo_Context(t *testing.T) {
2025 testCancelRequestWithChannelBeforeDo(t, true)
2027 func testCancelRequestWithChannelBeforeDo(t *testing.T, withCtx bool) {
2028 setParallel(t)
2029 defer afterTest(t)
2030 unblockc := make(chan bool)
2031 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
2032 <-unblockc
2034 defer ts.Close()
2035 defer close(unblockc)
2037 c := ts.Client()
2039 req, _ := NewRequest("GET", ts.URL, nil)
2040 if withCtx {
2041 ctx, cancel := context.WithCancel(context.Background())
2042 cancel()
2043 req = req.WithContext(ctx)
2044 } else {
2045 ch := make(chan struct{})
2046 req.Cancel = ch
2047 close(ch)
2050 _, err := c.Do(req)
2051 if ue, ok := err.(*url.Error); ok {
2052 err = ue.Err
2054 if withCtx {
2055 if err != context.Canceled {
2056 t.Errorf("Do error = %v; want %v", err, context.Canceled)
2058 } else {
2059 if err == nil || !strings.Contains(err.Error(), "canceled") {
2060 t.Errorf("Do error = %v; want cancelation", err)
2065 // Issue 11020. The returned error message should be errRequestCanceled
2066 func TestTransportCancelBeforeResponseHeaders(t *testing.T) {
2067 defer afterTest(t)
2069 serverConnCh := make(chan net.Conn, 1)
2070 tr := &Transport{
2071 Dial: func(network, addr string) (net.Conn, error) {
2072 cc, sc := net.Pipe()
2073 serverConnCh <- sc
2074 return cc, nil
2077 defer tr.CloseIdleConnections()
2078 errc := make(chan error, 1)
2079 req, _ := NewRequest("GET", "http://example.com/", nil)
2080 go func() {
2081 _, err := tr.RoundTrip(req)
2082 errc <- err
2085 sc := <-serverConnCh
2086 verb := make([]byte, 3)
2087 if _, err := io.ReadFull(sc, verb); err != nil {
2088 t.Errorf("Error reading HTTP verb from server: %v", err)
2090 if string(verb) != "GET" {
2091 t.Errorf("server received %q; want GET", verb)
2093 defer sc.Close()
2095 tr.CancelRequest(req)
2097 err := <-errc
2098 if err == nil {
2099 t.Fatalf("unexpected success from RoundTrip")
2101 if err != ExportErrRequestCanceled {
2102 t.Errorf("RoundTrip error = %v; want ExportErrRequestCanceled", err)
2106 // golang.org/issue/3672 -- Client can't close HTTP stream
2107 // Calling Close on a Response.Body used to just read until EOF.
2108 // Now it actually closes the TCP connection.
2109 func TestTransportCloseResponseBody(t *testing.T) {
2110 defer afterTest(t)
2111 writeErr := make(chan error, 1)
2112 msg := []byte("young\n")
2113 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
2114 for {
2115 _, err := w.Write(msg)
2116 if err != nil {
2117 writeErr <- err
2118 return
2120 w.(Flusher).Flush()
2123 defer ts.Close()
2125 c := ts.Client()
2126 tr := c.Transport.(*Transport)
2128 req, _ := NewRequest("GET", ts.URL, nil)
2129 defer tr.CancelRequest(req)
2131 res, err := c.Do(req)
2132 if err != nil {
2133 t.Fatal(err)
2136 const repeats = 3
2137 buf := make([]byte, len(msg)*repeats)
2138 want := bytes.Repeat(msg, repeats)
2140 _, err = io.ReadFull(res.Body, buf)
2141 if err != nil {
2142 t.Fatal(err)
2144 if !bytes.Equal(buf, want) {
2145 t.Fatalf("read %q; want %q", buf, want)
2147 didClose := make(chan error, 1)
2148 go func() {
2149 didClose <- res.Body.Close()
2151 select {
2152 case err := <-didClose:
2153 if err != nil {
2154 t.Errorf("Close = %v", err)
2156 case <-time.After(10 * time.Second):
2157 t.Fatal("too long waiting for close")
2159 select {
2160 case err := <-writeErr:
2161 if err == nil {
2162 t.Errorf("expected non-nil write error")
2164 case <-time.After(10 * time.Second):
2165 t.Fatal("too long waiting for write error")
2169 type fooProto struct{}
2171 func (fooProto) RoundTrip(req *Request) (*Response, error) {
2172 res := &Response{
2173 Status: "200 OK",
2174 StatusCode: 200,
2175 Header: make(Header),
2176 Body: ioutil.NopCloser(strings.NewReader("You wanted " + req.URL.String())),
2178 return res, nil
2181 func TestTransportAltProto(t *testing.T) {
2182 defer afterTest(t)
2183 tr := &Transport{}
2184 c := &Client{Transport: tr}
2185 tr.RegisterProtocol("foo", fooProto{})
2186 res, err := c.Get("foo://bar.com/path")
2187 if err != nil {
2188 t.Fatal(err)
2190 bodyb, err := ioutil.ReadAll(res.Body)
2191 if err != nil {
2192 t.Fatal(err)
2194 body := string(bodyb)
2195 if e := "You wanted foo://bar.com/path"; body != e {
2196 t.Errorf("got response %q, want %q", body, e)
2200 func TestTransportNoHost(t *testing.T) {
2201 defer afterTest(t)
2202 tr := &Transport{}
2203 _, err := tr.RoundTrip(&Request{
2204 Header: make(Header),
2205 URL: &url.URL{
2206 Scheme: "http",
2209 want := "http: no Host in request URL"
2210 if got := fmt.Sprint(err); got != want {
2211 t.Errorf("error = %v; want %q", err, want)
2215 // Issue 13311
2216 func TestTransportEmptyMethod(t *testing.T) {
2217 req, _ := NewRequest("GET", "http://foo.com/", nil)
2218 req.Method = "" // docs say "For client requests an empty string means GET"
2219 got, err := httputil.DumpRequestOut(req, false) // DumpRequestOut uses Transport
2220 if err != nil {
2221 t.Fatal(err)
2223 if !strings.Contains(string(got), "GET ") {
2224 t.Fatalf("expected substring 'GET '; got: %s", got)
2228 func TestTransportSocketLateBinding(t *testing.T) {
2229 setParallel(t)
2230 defer afterTest(t)
2232 mux := NewServeMux()
2233 fooGate := make(chan bool, 1)
2234 mux.HandleFunc("/foo", func(w ResponseWriter, r *Request) {
2235 w.Header().Set("foo-ipport", r.RemoteAddr)
2236 w.(Flusher).Flush()
2237 <-fooGate
2239 mux.HandleFunc("/bar", func(w ResponseWriter, r *Request) {
2240 w.Header().Set("bar-ipport", r.RemoteAddr)
2242 ts := httptest.NewServer(mux)
2243 defer ts.Close()
2245 dialGate := make(chan bool, 1)
2246 c := ts.Client()
2247 c.Transport.(*Transport).Dial = func(n, addr string) (net.Conn, error) {
2248 if <-dialGate {
2249 return net.Dial(n, addr)
2251 return nil, errors.New("manually closed")
2254 dialGate <- true // only allow one dial
2255 fooRes, err := c.Get(ts.URL + "/foo")
2256 if err != nil {
2257 t.Fatal(err)
2259 fooAddr := fooRes.Header.Get("foo-ipport")
2260 if fooAddr == "" {
2261 t.Fatal("No addr on /foo request")
2263 time.AfterFunc(200*time.Millisecond, func() {
2264 // let the foo response finish so we can use its
2265 // connection for /bar
2266 fooGate <- true
2267 io.Copy(ioutil.Discard, fooRes.Body)
2268 fooRes.Body.Close()
2271 barRes, err := c.Get(ts.URL + "/bar")
2272 if err != nil {
2273 t.Fatal(err)
2275 barAddr := barRes.Header.Get("bar-ipport")
2276 if barAddr != fooAddr {
2277 t.Fatalf("/foo came from conn %q; /bar came from %q instead", fooAddr, barAddr)
2279 barRes.Body.Close()
2280 dialGate <- false
2283 // Issue 2184
2284 func TestTransportReading100Continue(t *testing.T) {
2285 defer afterTest(t)
2287 const numReqs = 5
2288 reqBody := func(n int) string { return fmt.Sprintf("request body %d", n) }
2289 reqID := func(n int) string { return fmt.Sprintf("REQ-ID-%d", n) }
2291 send100Response := func(w *io.PipeWriter, r *io.PipeReader) {
2292 defer w.Close()
2293 defer r.Close()
2294 br := bufio.NewReader(r)
2295 n := 0
2296 for {
2298 req, err := ReadRequest(br)
2299 if err == io.EOF {
2300 return
2302 if err != nil {
2303 t.Error(err)
2304 return
2306 slurp, err := ioutil.ReadAll(req.Body)
2307 if err != nil {
2308 t.Errorf("Server request body slurp: %v", err)
2309 return
2311 id := req.Header.Get("Request-Id")
2312 resCode := req.Header.Get("X-Want-Response-Code")
2313 if resCode == "" {
2314 resCode = "100 Continue"
2315 if string(slurp) != reqBody(n) {
2316 t.Errorf("Server got %q, %v; want %q", slurp, err, reqBody(n))
2319 body := fmt.Sprintf("Response number %d", n)
2320 v := []byte(strings.Replace(fmt.Sprintf(`HTTP/1.1 %s
2321 Date: Thu, 28 Feb 2013 17:55:41 GMT
2323 HTTP/1.1 200 OK
2324 Content-Type: text/html
2325 Echo-Request-Id: %s
2326 Content-Length: %d
2328 %s`, resCode, id, len(body), body), "\n", "\r\n", -1))
2329 w.Write(v)
2330 if id == reqID(numReqs) {
2331 return
2337 tr := &Transport{
2338 Dial: func(n, addr string) (net.Conn, error) {
2339 sr, sw := io.Pipe() // server read/write
2340 cr, cw := io.Pipe() // client read/write
2341 conn := &rwTestConn{
2342 Reader: cr,
2343 Writer: sw,
2344 closeFunc: func() error {
2345 sw.Close()
2346 cw.Close()
2347 return nil
2350 go send100Response(cw, sr)
2351 return conn, nil
2353 DisableKeepAlives: false,
2355 defer tr.CloseIdleConnections()
2356 c := &Client{Transport: tr}
2358 testResponse := func(req *Request, name string, wantCode int) {
2359 t.Helper()
2360 res, err := c.Do(req)
2361 if err != nil {
2362 t.Fatalf("%s: Do: %v", name, err)
2364 if res.StatusCode != wantCode {
2365 t.Fatalf("%s: Response Statuscode=%d; want %d", name, res.StatusCode, wantCode)
2367 if id, idBack := req.Header.Get("Request-Id"), res.Header.Get("Echo-Request-Id"); id != "" && id != idBack {
2368 t.Errorf("%s: response id %q != request id %q", name, idBack, id)
2370 _, err = ioutil.ReadAll(res.Body)
2371 if err != nil {
2372 t.Fatalf("%s: Slurp error: %v", name, err)
2376 // Few 100 responses, making sure we're not off-by-one.
2377 for i := 1; i <= numReqs; i++ {
2378 req, _ := NewRequest("POST", "http://dummy.tld/", strings.NewReader(reqBody(i)))
2379 req.Header.Set("Request-Id", reqID(i))
2380 testResponse(req, fmt.Sprintf("100, %d/%d", i, numReqs), 200)
2384 // Issue 17739: the HTTP client must ignore any unknown 1xx
2385 // informational responses before the actual response.
2386 func TestTransportIgnore1xxResponses(t *testing.T) {
2387 setParallel(t)
2388 defer afterTest(t)
2389 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) {
2390 conn, buf, _ := w.(Hijacker).Hijack()
2391 buf.Write([]byte("HTTP/1.1 123 OneTwoThree\r\nFoo: bar\r\n\r\nHTTP/1.1 200 OK\r\nBar: baz\r\nContent-Length: 5\r\n\r\nHello"))
2392 buf.Flush()
2393 conn.Close()
2395 defer cst.close()
2396 cst.tr.DisableKeepAlives = true // prevent log spam; our test server is hanging up anyway
2398 var got bytes.Buffer
2400 req, _ := NewRequest("GET", cst.ts.URL, nil)
2401 req = req.WithContext(httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{
2402 Got1xxResponse: func(code int, header textproto.MIMEHeader) error {
2403 fmt.Fprintf(&got, "1xx: code=%v, header=%v\n", code, header)
2404 return nil
2407 res, err := cst.c.Do(req)
2408 if err != nil {
2409 t.Fatal(err)
2411 defer res.Body.Close()
2413 res.Write(&got)
2414 want := "1xx: code=123, header=map[Foo:[bar]]\nHTTP/1.1 200 OK\r\nContent-Length: 5\r\nBar: baz\r\n\r\nHello"
2415 if got.String() != want {
2416 t.Errorf(" got: %q\nwant: %q\n", got.Bytes(), want)
2420 func TestTransportLimits1xxResponses(t *testing.T) {
2421 setParallel(t)
2422 defer afterTest(t)
2423 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) {
2424 conn, buf, _ := w.(Hijacker).Hijack()
2425 for i := 0; i < 10; i++ {
2426 buf.Write([]byte("HTTP/1.1 123 OneTwoThree\r\n\r\n"))
2428 buf.Write([]byte("HTTP/1.1 204 No Content\r\n\r\n"))
2429 buf.Flush()
2430 conn.Close()
2432 defer cst.close()
2433 cst.tr.DisableKeepAlives = true // prevent log spam; our test server is hanging up anyway
2435 res, err := cst.c.Get(cst.ts.URL)
2436 if res != nil {
2437 defer res.Body.Close()
2439 got := fmt.Sprint(err)
2440 wantSub := "too many 1xx informational responses"
2441 if !strings.Contains(got, wantSub) {
2442 t.Errorf("Get error = %v; want substring %q", err, wantSub)
2446 // Issue 26161: the HTTP client must treat 101 responses
2447 // as the final response.
2448 func TestTransportTreat101Terminal(t *testing.T) {
2449 setParallel(t)
2450 defer afterTest(t)
2451 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) {
2452 conn, buf, _ := w.(Hijacker).Hijack()
2453 buf.Write([]byte("HTTP/1.1 101 Switching Protocols\r\n\r\n"))
2454 buf.Write([]byte("HTTP/1.1 204 No Content\r\n\r\n"))
2455 buf.Flush()
2456 conn.Close()
2458 defer cst.close()
2459 res, err := cst.c.Get(cst.ts.URL)
2460 if err != nil {
2461 t.Fatal(err)
2463 defer res.Body.Close()
2464 if res.StatusCode != StatusSwitchingProtocols {
2465 t.Errorf("StatusCode = %v; want 101 Switching Protocols", res.StatusCode)
2469 type proxyFromEnvTest struct {
2470 req string // URL to fetch; blank means "http://example.com"
2472 env string // HTTP_PROXY
2473 httpsenv string // HTTPS_PROXY
2474 noenv string // NO_PROXY
2475 reqmeth string // REQUEST_METHOD
2477 want string
2478 wanterr error
2481 func (t proxyFromEnvTest) String() string {
2482 var buf bytes.Buffer
2483 space := func() {
2484 if buf.Len() > 0 {
2485 buf.WriteByte(' ')
2488 if t.env != "" {
2489 fmt.Fprintf(&buf, "http_proxy=%q", t.env)
2491 if t.httpsenv != "" {
2492 space()
2493 fmt.Fprintf(&buf, "https_proxy=%q", t.httpsenv)
2495 if t.noenv != "" {
2496 space()
2497 fmt.Fprintf(&buf, "no_proxy=%q", t.noenv)
2499 if t.reqmeth != "" {
2500 space()
2501 fmt.Fprintf(&buf, "request_method=%q", t.reqmeth)
2503 req := "http://example.com"
2504 if t.req != "" {
2505 req = t.req
2507 space()
2508 fmt.Fprintf(&buf, "req=%q", req)
2509 return strings.TrimSpace(buf.String())
2512 var proxyFromEnvTests = []proxyFromEnvTest{
2513 {env: "127.0.0.1:8080", want: "http://127.0.0.1:8080"},
2514 {env: "cache.corp.example.com:1234", want: "http://cache.corp.example.com:1234"},
2515 {env: "cache.corp.example.com", want: "http://cache.corp.example.com"},
2516 {env: "https://cache.corp.example.com", want: "https://cache.corp.example.com"},
2517 {env: "http://127.0.0.1:8080", want: "http://127.0.0.1:8080"},
2518 {env: "https://127.0.0.1:8080", want: "https://127.0.0.1:8080"},
2519 {env: "socks5://127.0.0.1", want: "socks5://127.0.0.1"},
2521 // Don't use secure for http
2522 {req: "http://insecure.tld/", env: "http.proxy.tld", httpsenv: "secure.proxy.tld", want: "http://http.proxy.tld"},
2523 // Use secure for https.
2524 {req: "https://secure.tld/", env: "http.proxy.tld", httpsenv: "secure.proxy.tld", want: "http://secure.proxy.tld"},
2525 {req: "https://secure.tld/", env: "http.proxy.tld", httpsenv: "https://secure.proxy.tld", want: "https://secure.proxy.tld"},
2527 // Issue 16405: don't use HTTP_PROXY in a CGI environment,
2528 // where HTTP_PROXY can be attacker-controlled.
2529 {env: "http://10.1.2.3:8080", reqmeth: "POST",
2530 want: "<nil>",
2531 wanterr: errors.New("refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy")},
2533 {want: "<nil>"},
2535 {noenv: "example.com", req: "http://example.com/", env: "proxy", want: "<nil>"},
2536 {noenv: ".example.com", req: "http://example.com/", env: "proxy", want: "http://proxy"},
2537 {noenv: "ample.com", req: "http://example.com/", env: "proxy", want: "http://proxy"},
2538 {noenv: "example.com", req: "http://foo.example.com/", env: "proxy", want: "<nil>"},
2539 {noenv: ".foo.com", req: "http://example.com/", env: "proxy", want: "http://proxy"},
2542 func testProxyForRequest(t *testing.T, tt proxyFromEnvTest, proxyForRequest func(req *Request) (*url.URL, error)) {
2543 t.Helper()
2544 reqURL := tt.req
2545 if reqURL == "" {
2546 reqURL = "http://example.com"
2548 req, _ := NewRequest("GET", reqURL, nil)
2549 url, err := proxyForRequest(req)
2550 if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e {
2551 t.Errorf("%v: got error = %q, want %q", tt, g, e)
2552 return
2554 if got := fmt.Sprintf("%s", url); got != tt.want {
2555 t.Errorf("%v: got URL = %q, want %q", tt, url, tt.want)
2559 func TestProxyFromEnvironment(t *testing.T) {
2560 ResetProxyEnv()
2561 defer ResetProxyEnv()
2562 for _, tt := range proxyFromEnvTests {
2563 testProxyForRequest(t, tt, func(req *Request) (*url.URL, error) {
2564 os.Setenv("HTTP_PROXY", tt.env)
2565 os.Setenv("HTTPS_PROXY", tt.httpsenv)
2566 os.Setenv("NO_PROXY", tt.noenv)
2567 os.Setenv("REQUEST_METHOD", tt.reqmeth)
2568 ResetCachedEnvironment()
2569 return ProxyFromEnvironment(req)
2574 func TestProxyFromEnvironmentLowerCase(t *testing.T) {
2575 ResetProxyEnv()
2576 defer ResetProxyEnv()
2577 for _, tt := range proxyFromEnvTests {
2578 testProxyForRequest(t, tt, func(req *Request) (*url.URL, error) {
2579 os.Setenv("http_proxy", tt.env)
2580 os.Setenv("https_proxy", tt.httpsenv)
2581 os.Setenv("no_proxy", tt.noenv)
2582 os.Setenv("REQUEST_METHOD", tt.reqmeth)
2583 ResetCachedEnvironment()
2584 return ProxyFromEnvironment(req)
2589 func TestIdleConnChannelLeak(t *testing.T) {
2590 // Not parallel: uses global test hooks.
2591 var mu sync.Mutex
2592 var n int
2594 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
2595 mu.Lock()
2597 mu.Unlock()
2599 defer ts.Close()
2601 const nReqs = 5
2602 didRead := make(chan bool, nReqs)
2603 SetReadLoopBeforeNextReadHook(func() { didRead <- true })
2604 defer SetReadLoopBeforeNextReadHook(nil)
2606 c := ts.Client()
2607 tr := c.Transport.(*Transport)
2608 tr.Dial = func(netw, addr string) (net.Conn, error) {
2609 return net.Dial(netw, ts.Listener.Addr().String())
2612 // First, without keep-alives.
2613 for _, disableKeep := range []bool{true, false} {
2614 tr.DisableKeepAlives = disableKeep
2615 for i := 0; i < nReqs; i++ {
2616 _, err := c.Get(fmt.Sprintf("http://foo-host-%d.tld/", i))
2617 if err != nil {
2618 t.Fatal(err)
2620 // Note: no res.Body.Close is needed here, since the
2621 // response Content-Length is zero. Perhaps the test
2622 // should be more explicit and use a HEAD, but tests
2623 // elsewhere guarantee that zero byte responses generate
2624 // a "Content-Length: 0" instead of chunking.
2627 // At this point, each of the 5 Transport.readLoop goroutines
2628 // are scheduling noting that there are no response bodies (see
2629 // earlier comment), and are then calling putIdleConn, which
2630 // decrements this count. Usually that happens quickly, which is
2631 // why this test has seemed to work for ages. But it's still
2632 // racey: we have wait for them to finish first. See Issue 10427
2633 for i := 0; i < nReqs; i++ {
2634 <-didRead
2637 if got := tr.IdleConnChMapSizeForTesting(); got != 0 {
2638 t.Fatalf("ForDisableKeepAlives = %v, map size = %d; want 0", disableKeep, got)
2643 // Verify the status quo: that the Client.Post function coerces its
2644 // body into a ReadCloser if it's a Closer, and that the Transport
2645 // then closes it.
2646 func TestTransportClosesRequestBody(t *testing.T) {
2647 defer afterTest(t)
2648 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
2649 io.Copy(ioutil.Discard, r.Body)
2651 defer ts.Close()
2653 c := ts.Client()
2655 closes := 0
2657 res, err := c.Post(ts.URL, "text/plain", countCloseReader{&closes, strings.NewReader("hello")})
2658 if err != nil {
2659 t.Fatal(err)
2661 res.Body.Close()
2662 if closes != 1 {
2663 t.Errorf("closes = %d; want 1", closes)
2667 func TestTransportTLSHandshakeTimeout(t *testing.T) {
2668 defer afterTest(t)
2669 if testing.Short() {
2670 t.Skip("skipping in short mode")
2672 ln := newLocalListener(t)
2673 defer ln.Close()
2674 testdonec := make(chan struct{})
2675 defer close(testdonec)
2677 go func() {
2678 c, err := ln.Accept()
2679 if err != nil {
2680 t.Error(err)
2681 return
2683 <-testdonec
2684 c.Close()
2687 getdonec := make(chan struct{})
2688 go func() {
2689 defer close(getdonec)
2690 tr := &Transport{
2691 Dial: func(_, _ string) (net.Conn, error) {
2692 return net.Dial("tcp", ln.Addr().String())
2694 TLSHandshakeTimeout: 250 * time.Millisecond,
2696 cl := &Client{Transport: tr}
2697 _, err := cl.Get("https://dummy.tld/")
2698 if err == nil {
2699 t.Error("expected error")
2700 return
2702 ue, ok := err.(*url.Error)
2703 if !ok {
2704 t.Errorf("expected url.Error; got %#v", err)
2705 return
2707 ne, ok := ue.Err.(net.Error)
2708 if !ok {
2709 t.Errorf("expected net.Error; got %#v", err)
2710 return
2712 if !ne.Timeout() {
2713 t.Errorf("expected timeout error; got %v", err)
2715 if !strings.Contains(err.Error(), "handshake timeout") {
2716 t.Errorf("expected 'handshake timeout' in error; got %v", err)
2719 select {
2720 case <-getdonec:
2721 case <-time.After(5 * time.Second):
2722 t.Error("test timeout; TLS handshake hung?")
2726 // Trying to repro golang.org/issue/3514
2727 func TestTLSServerClosesConnection(t *testing.T) {
2728 defer afterTest(t)
2729 testenv.SkipFlaky(t, 7634)
2731 closedc := make(chan bool, 1)
2732 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
2733 if strings.Contains(r.URL.Path, "/keep-alive-then-die") {
2734 conn, _, _ := w.(Hijacker).Hijack()
2735 conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nfoo"))
2736 conn.Close()
2737 closedc <- true
2738 return
2740 fmt.Fprintf(w, "hello")
2742 defer ts.Close()
2744 c := ts.Client()
2745 tr := c.Transport.(*Transport)
2747 var nSuccess = 0
2748 var errs []error
2749 const trials = 20
2750 for i := 0; i < trials; i++ {
2751 tr.CloseIdleConnections()
2752 res, err := c.Get(ts.URL + "/keep-alive-then-die")
2753 if err != nil {
2754 t.Fatal(err)
2756 <-closedc
2757 slurp, err := ioutil.ReadAll(res.Body)
2758 if err != nil {
2759 t.Fatal(err)
2761 if string(slurp) != "foo" {
2762 t.Errorf("Got %q, want foo", slurp)
2765 // Now try again and see if we successfully
2766 // pick a new connection.
2767 res, err = c.Get(ts.URL + "/")
2768 if err != nil {
2769 errs = append(errs, err)
2770 continue
2772 slurp, err = ioutil.ReadAll(res.Body)
2773 if err != nil {
2774 errs = append(errs, err)
2775 continue
2777 nSuccess++
2779 if nSuccess > 0 {
2780 t.Logf("successes = %d of %d", nSuccess, trials)
2781 } else {
2782 t.Errorf("All runs failed:")
2784 for _, err := range errs {
2785 t.Logf(" err: %v", err)
2789 // byteFromChanReader is an io.Reader that reads a single byte at a
2790 // time from the channel. When the channel is closed, the reader
2791 // returns io.EOF.
2792 type byteFromChanReader chan byte
2794 func (c byteFromChanReader) Read(p []byte) (n int, err error) {
2795 if len(p) == 0 {
2796 return
2798 b, ok := <-c
2799 if !ok {
2800 return 0, io.EOF
2802 p[0] = b
2803 return 1, nil
2806 // Verifies that the Transport doesn't reuse a connection in the case
2807 // where the server replies before the request has been fully
2808 // written. We still honor that reply (see TestIssue3595), but don't
2809 // send future requests on the connection because it's then in a
2810 // questionable state.
2811 // golang.org/issue/7569
2812 func TestTransportNoReuseAfterEarlyResponse(t *testing.T) {
2813 setParallel(t)
2814 defer afterTest(t)
2815 var sconn struct {
2816 sync.Mutex
2817 c net.Conn
2819 var getOkay bool
2820 closeConn := func() {
2821 sconn.Lock()
2822 defer sconn.Unlock()
2823 if sconn.c != nil {
2824 sconn.c.Close()
2825 sconn.c = nil
2826 if !getOkay {
2827 t.Logf("Closed server connection")
2831 defer closeConn()
2833 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
2834 if r.Method == "GET" {
2835 io.WriteString(w, "bar")
2836 return
2838 conn, _, _ := w.(Hijacker).Hijack()
2839 sconn.Lock()
2840 sconn.c = conn
2841 sconn.Unlock()
2842 conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nfoo")) // keep-alive
2843 go io.Copy(ioutil.Discard, conn)
2845 defer ts.Close()
2846 c := ts.Client()
2848 const bodySize = 256 << 10
2849 finalBit := make(byteFromChanReader, 1)
2850 req, _ := NewRequest("POST", ts.URL, io.MultiReader(io.LimitReader(neverEnding('x'), bodySize-1), finalBit))
2851 req.ContentLength = bodySize
2852 res, err := c.Do(req)
2853 if err := wantBody(res, err, "foo"); err != nil {
2854 t.Errorf("POST response: %v", err)
2856 donec := make(chan bool)
2857 go func() {
2858 defer close(donec)
2859 res, err = c.Get(ts.URL)
2860 if err := wantBody(res, err, "bar"); err != nil {
2861 t.Errorf("GET response: %v", err)
2862 return
2864 getOkay = true // suppress test noise
2866 time.AfterFunc(5*time.Second, closeConn)
2867 select {
2868 case <-donec:
2869 finalBit <- 'x' // unblock the writeloop of the first Post
2870 close(finalBit)
2871 case <-time.After(7 * time.Second):
2872 t.Fatal("timeout waiting for GET request to finish")
2876 // Tests that we don't leak Transport persistConn.readLoop goroutines
2877 // when a server hangs up immediately after saying it would keep-alive.
2878 func TestTransportIssue10457(t *testing.T) {
2879 defer afterTest(t) // used to fail in goroutine leak check
2880 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
2881 // Send a response with no body, keep-alive
2882 // (implicit), and then lie and immediately close the
2883 // connection. This forces the Transport's readLoop to
2884 // immediately Peek an io.EOF and get to the point
2885 // that used to hang.
2886 conn, _, _ := w.(Hijacker).Hijack()
2887 conn.Write([]byte("HTTP/1.1 200 OK\r\nFoo: Bar\r\nContent-Length: 0\r\n\r\n")) // keep-alive
2888 conn.Close()
2890 defer ts.Close()
2891 c := ts.Client()
2893 res, err := c.Get(ts.URL)
2894 if err != nil {
2895 t.Fatalf("Get: %v", err)
2897 defer res.Body.Close()
2899 // Just a sanity check that we at least get the response. The real
2900 // test here is that the "defer afterTest" above doesn't find any
2901 // leaked goroutines.
2902 if got, want := res.Header.Get("Foo"), "Bar"; got != want {
2903 t.Errorf("Foo header = %q; want %q", got, want)
2907 type errorReader struct {
2908 err error
2911 func (e errorReader) Read(p []byte) (int, error) { return 0, e.err }
2913 type closerFunc func() error
2915 func (f closerFunc) Close() error { return f() }
2917 type writerFuncConn struct {
2918 net.Conn
2919 write func(p []byte) (n int, err error)
2922 func (c writerFuncConn) Write(p []byte) (n int, err error) { return c.write(p) }
2924 // Issues 4677, 18241, and 17844. If we try to reuse a connection that the
2925 // server is in the process of closing, we may end up successfully writing out
2926 // our request (or a portion of our request) only to find a connection error
2927 // when we try to read from (or finish writing to) the socket.
2929 // NOTE: we resend a request only if:
2930 // - we reused a keep-alive connection
2931 // - we haven't yet received any header data
2932 // - either we wrote no bytes to the server, or the request is idempotent
2933 // This automatically prevents an infinite resend loop because we'll run out of
2934 // the cached keep-alive connections eventually.
2935 func TestRetryRequestsOnError(t *testing.T) {
2936 newRequest := func(method, urlStr string, body io.Reader) *Request {
2937 req, err := NewRequest(method, urlStr, body)
2938 if err != nil {
2939 t.Fatal(err)
2941 return req
2944 testCases := []struct {
2945 name string
2946 failureN int
2947 failureErr error
2948 // Note that we can't just re-use the Request object across calls to c.Do
2949 // because we need to rewind Body between calls. (GetBody is only used to
2950 // rewind Body on failure and redirects, not just because it's done.)
2951 req func() *Request
2952 reqString string
2955 name: "IdempotentNoBodySomeWritten",
2956 // Believe that we've written some bytes to the server, so we know we're
2957 // not just in the "retry when no bytes sent" case".
2958 failureN: 1,
2959 // Use the specific error that shouldRetryRequest looks for with idempotent requests.
2960 failureErr: ExportErrServerClosedIdle,
2961 req: func() *Request {
2962 return newRequest("GET", "http://fake.golang", nil)
2964 reqString: `GET / HTTP/1.1\r\nHost: fake.golang\r\nUser-Agent: Go-http-client/1.1\r\nAccept-Encoding: gzip\r\n\r\n`,
2967 name: "IdempotentGetBodySomeWritten",
2968 // Believe that we've written some bytes to the server, so we know we're
2969 // not just in the "retry when no bytes sent" case".
2970 failureN: 1,
2971 // Use the specific error that shouldRetryRequest looks for with idempotent requests.
2972 failureErr: ExportErrServerClosedIdle,
2973 req: func() *Request {
2974 return newRequest("GET", "http://fake.golang", strings.NewReader("foo\n"))
2976 reqString: `GET / HTTP/1.1\r\nHost: fake.golang\r\nUser-Agent: Go-http-client/1.1\r\nContent-Length: 4\r\nAccept-Encoding: gzip\r\n\r\nfoo\n`,
2979 name: "NothingWrittenNoBody",
2980 // It's key that we return 0 here -- that's what enables Transport to know
2981 // that nothing was written, even though this is a non-idempotent request.
2982 failureN: 0,
2983 failureErr: errors.New("second write fails"),
2984 req: func() *Request {
2985 return newRequest("DELETE", "http://fake.golang", nil)
2987 reqString: `DELETE / HTTP/1.1\r\nHost: fake.golang\r\nUser-Agent: Go-http-client/1.1\r\nAccept-Encoding: gzip\r\n\r\n`,
2990 name: "NothingWrittenGetBody",
2991 // It's key that we return 0 here -- that's what enables Transport to know
2992 // that nothing was written, even though this is a non-idempotent request.
2993 failureN: 0,
2994 failureErr: errors.New("second write fails"),
2995 // Note that NewRequest will set up GetBody for strings.Reader, which is
2996 // required for the retry to occur
2997 req: func() *Request {
2998 return newRequest("POST", "http://fake.golang", strings.NewReader("foo\n"))
3000 reqString: `POST / HTTP/1.1\r\nHost: fake.golang\r\nUser-Agent: Go-http-client/1.1\r\nContent-Length: 4\r\nAccept-Encoding: gzip\r\n\r\nfoo\n`,
3004 for _, tc := range testCases {
3005 t.Run(tc.name, func(t *testing.T) {
3006 defer afterTest(t)
3008 var (
3009 mu sync.Mutex
3010 logbuf bytes.Buffer
3012 logf := func(format string, args ...interface{}) {
3013 mu.Lock()
3014 defer mu.Unlock()
3015 fmt.Fprintf(&logbuf, format, args...)
3016 logbuf.WriteByte('\n')
3019 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
3020 logf("Handler")
3021 w.Header().Set("X-Status", "ok")
3023 defer ts.Close()
3025 var writeNumAtomic int32
3026 c := ts.Client()
3027 c.Transport.(*Transport).Dial = func(network, addr string) (net.Conn, error) {
3028 logf("Dial")
3029 c, err := net.Dial(network, ts.Listener.Addr().String())
3030 if err != nil {
3031 logf("Dial error: %v", err)
3032 return nil, err
3034 return &writerFuncConn{
3035 Conn: c,
3036 write: func(p []byte) (n int, err error) {
3037 if atomic.AddInt32(&writeNumAtomic, 1) == 2 {
3038 logf("intentional write failure")
3039 return tc.failureN, tc.failureErr
3041 logf("Write(%q)", p)
3042 return c.Write(p)
3044 }, nil
3047 SetRoundTripRetried(func() {
3048 logf("Retried.")
3050 defer SetRoundTripRetried(nil)
3052 for i := 0; i < 3; i++ {
3053 t0 := time.Now()
3054 res, err := c.Do(tc.req())
3055 if err != nil {
3056 if time.Since(t0) < MaxWriteWaitBeforeConnReuse/2 {
3057 mu.Lock()
3058 got := logbuf.String()
3059 mu.Unlock()
3060 t.Fatalf("i=%d: Do = %v; log:\n%s", i, err, got)
3062 t.Skipf("connection likely wasn't recycled within %d, interfering with actual test; skipping", MaxWriteWaitBeforeConnReuse)
3064 res.Body.Close()
3067 mu.Lock()
3068 got := logbuf.String()
3069 mu.Unlock()
3070 want := fmt.Sprintf(`Dial
3071 Write("%s")
3072 Handler
3073 intentional write failure
3074 Retried.
3075 Dial
3076 Write("%s")
3077 Handler
3078 Write("%s")
3079 Handler
3080 `, tc.reqString, tc.reqString, tc.reqString)
3081 if got != want {
3082 t.Errorf("Log of events differs. Got:\n%s\nWant:\n%s", got, want)
3088 // Issue 6981
3089 func TestTransportClosesBodyOnError(t *testing.T) {
3090 setParallel(t)
3091 defer afterTest(t)
3092 readBody := make(chan error, 1)
3093 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
3094 _, err := ioutil.ReadAll(r.Body)
3095 readBody <- err
3097 defer ts.Close()
3098 c := ts.Client()
3099 fakeErr := errors.New("fake error")
3100 didClose := make(chan bool, 1)
3101 req, _ := NewRequest("POST", ts.URL, struct {
3102 io.Reader
3103 io.Closer
3105 io.MultiReader(io.LimitReader(neverEnding('x'), 1<<20), errorReader{fakeErr}),
3106 closerFunc(func() error {
3107 select {
3108 case didClose <- true:
3109 default:
3111 return nil
3114 res, err := c.Do(req)
3115 if res != nil {
3116 defer res.Body.Close()
3118 if err == nil || !strings.Contains(err.Error(), fakeErr.Error()) {
3119 t.Fatalf("Do error = %v; want something containing %q", err, fakeErr.Error())
3121 select {
3122 case err := <-readBody:
3123 if err == nil {
3124 t.Errorf("Unexpected success reading request body from handler; want 'unexpected EOF reading trailer'")
3126 case <-time.After(5 * time.Second):
3127 t.Error("timeout waiting for server handler to complete")
3129 select {
3130 case <-didClose:
3131 default:
3132 t.Errorf("didn't see Body.Close")
3136 func TestTransportDialTLS(t *testing.T) {
3137 setParallel(t)
3138 defer afterTest(t)
3139 var mu sync.Mutex // guards following
3140 var gotReq, didDial bool
3142 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
3143 mu.Lock()
3144 gotReq = true
3145 mu.Unlock()
3147 defer ts.Close()
3148 c := ts.Client()
3149 c.Transport.(*Transport).DialTLS = func(netw, addr string) (net.Conn, error) {
3150 mu.Lock()
3151 didDial = true
3152 mu.Unlock()
3153 c, err := tls.Dial(netw, addr, c.Transport.(*Transport).TLSClientConfig)
3154 if err != nil {
3155 return nil, err
3157 return c, c.Handshake()
3160 res, err := c.Get(ts.URL)
3161 if err != nil {
3162 t.Fatal(err)
3164 res.Body.Close()
3165 mu.Lock()
3166 if !gotReq {
3167 t.Error("didn't get request")
3169 if !didDial {
3170 t.Error("didn't use dial hook")
3174 // Test for issue 8755
3175 // Ensure that if a proxy returns an error, it is exposed by RoundTrip
3176 func TestRoundTripReturnsProxyError(t *testing.T) {
3177 badProxy := func(*Request) (*url.URL, error) {
3178 return nil, errors.New("errorMessage")
3181 tr := &Transport{Proxy: badProxy}
3183 req, _ := NewRequest("GET", "http://example.com", nil)
3185 _, err := tr.RoundTrip(req)
3187 if err == nil {
3188 t.Error("Expected proxy error to be returned by RoundTrip")
3192 // tests that putting an idle conn after a call to CloseIdleConns does return it
3193 func TestTransportCloseIdleConnsThenReturn(t *testing.T) {
3194 tr := &Transport{}
3195 wantIdle := func(when string, n int) bool {
3196 got := tr.IdleConnCountForTesting("http", "example.com") // key used by PutIdleTestConn
3197 if got == n {
3198 return true
3200 t.Errorf("%s: idle conns = %d; want %d", when, got, n)
3201 return false
3203 wantIdle("start", 0)
3204 if !tr.PutIdleTestConn("http", "example.com") {
3205 t.Fatal("put failed")
3207 if !tr.PutIdleTestConn("http", "example.com") {
3208 t.Fatal("second put failed")
3210 wantIdle("after put", 2)
3211 tr.CloseIdleConnections()
3212 if !tr.IsIdleForTesting() {
3213 t.Error("should be idle after CloseIdleConnections")
3215 wantIdle("after close idle", 0)
3216 if tr.PutIdleTestConn("http", "example.com") {
3217 t.Fatal("put didn't fail")
3219 wantIdle("after second put", 0)
3221 tr.RequestIdleConnChForTesting() // should toggle the transport out of idle mode
3222 if tr.IsIdleForTesting() {
3223 t.Error("shouldn't be idle after RequestIdleConnChForTesting")
3225 if !tr.PutIdleTestConn("http", "example.com") {
3226 t.Fatal("after re-activation")
3228 wantIdle("after final put", 1)
3231 // This tests that an client requesting a content range won't also
3232 // implicitly ask for gzip support. If they want that, they need to do it
3233 // on their own.
3234 // golang.org/issue/8923
3235 func TestTransportRangeAndGzip(t *testing.T) {
3236 defer afterTest(t)
3237 reqc := make(chan *Request, 1)
3238 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
3239 reqc <- r
3241 defer ts.Close()
3242 c := ts.Client()
3244 req, _ := NewRequest("GET", ts.URL, nil)
3245 req.Header.Set("Range", "bytes=7-11")
3246 res, err := c.Do(req)
3247 if err != nil {
3248 t.Fatal(err)
3251 select {
3252 case r := <-reqc:
3253 if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
3254 t.Error("Transport advertised gzip support in the Accept header")
3256 if r.Header.Get("Range") == "" {
3257 t.Error("no Range in request")
3259 case <-time.After(10 * time.Second):
3260 t.Fatal("timeout")
3262 res.Body.Close()
3265 // Test for issue 10474
3266 func TestTransportResponseCancelRace(t *testing.T) {
3267 defer afterTest(t)
3269 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
3270 // important that this response has a body.
3271 var b [1024]byte
3272 w.Write(b[:])
3274 defer ts.Close()
3275 tr := ts.Client().Transport.(*Transport)
3277 req, err := NewRequest("GET", ts.URL, nil)
3278 if err != nil {
3279 t.Fatal(err)
3281 res, err := tr.RoundTrip(req)
3282 if err != nil {
3283 t.Fatal(err)
3285 // If we do an early close, Transport just throws the connection away and
3286 // doesn't reuse it. In order to trigger the bug, it has to reuse the connection
3287 // so read the body
3288 if _, err := io.Copy(ioutil.Discard, res.Body); err != nil {
3289 t.Fatal(err)
3292 req2, err := NewRequest("GET", ts.URL, nil)
3293 if err != nil {
3294 t.Fatal(err)
3296 tr.CancelRequest(req)
3297 res, err = tr.RoundTrip(req2)
3298 if err != nil {
3299 t.Fatal(err)
3301 res.Body.Close()
3304 // Test for issue 19248: Content-Encoding's value is case insensitive.
3305 func TestTransportContentEncodingCaseInsensitive(t *testing.T) {
3306 setParallel(t)
3307 defer afterTest(t)
3308 for _, ce := range []string{"gzip", "GZIP"} {
3309 ce := ce
3310 t.Run(ce, func(t *testing.T) {
3311 const encodedString = "Hello Gopher"
3312 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
3313 w.Header().Set("Content-Encoding", ce)
3314 gz := gzip.NewWriter(w)
3315 gz.Write([]byte(encodedString))
3316 gz.Close()
3318 defer ts.Close()
3320 res, err := ts.Client().Get(ts.URL)
3321 if err != nil {
3322 t.Fatal(err)
3325 body, err := ioutil.ReadAll(res.Body)
3326 res.Body.Close()
3327 if err != nil {
3328 t.Fatal(err)
3331 if string(body) != encodedString {
3332 t.Fatalf("Expected body %q, got: %q\n", encodedString, string(body))
3338 func TestTransportDialCancelRace(t *testing.T) {
3339 defer afterTest(t)
3341 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
3342 defer ts.Close()
3343 tr := ts.Client().Transport.(*Transport)
3345 req, err := NewRequest("GET", ts.URL, nil)
3346 if err != nil {
3347 t.Fatal(err)
3349 SetEnterRoundTripHook(func() {
3350 tr.CancelRequest(req)
3352 defer SetEnterRoundTripHook(nil)
3353 res, err := tr.RoundTrip(req)
3354 if err != ExportErrRequestCanceled {
3355 t.Errorf("expected canceled request error; got %v", err)
3356 if err == nil {
3357 res.Body.Close()
3362 // logWritesConn is a net.Conn that logs each Write call to writes
3363 // and then proxies to w.
3364 // It proxies Read calls to a reader it receives from rch.
3365 type logWritesConn struct {
3366 net.Conn // nil. crash on use.
3368 w io.Writer
3370 rch <-chan io.Reader
3371 r io.Reader // nil until received by rch
3373 mu sync.Mutex
3374 writes []string
3377 func (c *logWritesConn) Write(p []byte) (n int, err error) {
3378 c.mu.Lock()
3379 defer c.mu.Unlock()
3380 c.writes = append(c.writes, string(p))
3381 return c.w.Write(p)
3384 func (c *logWritesConn) Read(p []byte) (n int, err error) {
3385 if c.r == nil {
3386 c.r = <-c.rch
3388 return c.r.Read(p)
3391 func (c *logWritesConn) Close() error { return nil }
3393 // Issue 6574
3394 func TestTransportFlushesBodyChunks(t *testing.T) {
3395 defer afterTest(t)
3396 resBody := make(chan io.Reader, 1)
3397 connr, connw := io.Pipe() // connection pipe pair
3398 lw := &logWritesConn{
3399 rch: resBody,
3400 w: connw,
3402 tr := &Transport{
3403 Dial: func(network, addr string) (net.Conn, error) {
3404 return lw, nil
3407 bodyr, bodyw := io.Pipe() // body pipe pair
3408 go func() {
3409 defer bodyw.Close()
3410 for i := 0; i < 3; i++ {
3411 fmt.Fprintf(bodyw, "num%d\n", i)
3414 resc := make(chan *Response)
3415 go func() {
3416 req, _ := NewRequest("POST", "http://localhost:8080", bodyr)
3417 req.Header.Set("User-Agent", "x") // known value for test
3418 res, err := tr.RoundTrip(req)
3419 if err != nil {
3420 t.Errorf("RoundTrip: %v", err)
3421 close(resc)
3422 return
3424 resc <- res
3427 // Fully consume the request before checking the Write log vs. want.
3428 req, err := ReadRequest(bufio.NewReader(connr))
3429 if err != nil {
3430 t.Fatal(err)
3432 io.Copy(ioutil.Discard, req.Body)
3434 // Unblock the transport's roundTrip goroutine.
3435 resBody <- strings.NewReader("HTTP/1.1 204 No Content\r\nConnection: close\r\n\r\n")
3436 res, ok := <-resc
3437 if !ok {
3438 return
3440 defer res.Body.Close()
3442 want := []string{
3443 "POST / HTTP/1.1\r\nHost: localhost:8080\r\nUser-Agent: x\r\nTransfer-Encoding: chunked\r\nAccept-Encoding: gzip\r\n\r\n",
3444 "5\r\nnum0\n\r\n",
3445 "5\r\nnum1\n\r\n",
3446 "5\r\nnum2\n\r\n",
3447 "0\r\n\r\n",
3449 if !reflect.DeepEqual(lw.writes, want) {
3450 t.Errorf("Writes differed.\n Got: %q\nWant: %q\n", lw.writes, want)
3454 // Issue 22088: flush Transport request headers if we're not sure the body won't block on read.
3455 func TestTransportFlushesRequestHeader(t *testing.T) {
3456 defer afterTest(t)
3457 gotReq := make(chan struct{})
3458 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) {
3459 close(gotReq)
3461 defer cst.close()
3463 pr, pw := io.Pipe()
3464 req, err := NewRequest("POST", cst.ts.URL, pr)
3465 if err != nil {
3466 t.Fatal(err)
3468 gotRes := make(chan struct{})
3469 go func() {
3470 defer close(gotRes)
3471 res, err := cst.tr.RoundTrip(req)
3472 if err != nil {
3473 t.Error(err)
3474 return
3476 res.Body.Close()
3479 select {
3480 case <-gotReq:
3481 pw.Close()
3482 case <-time.After(5 * time.Second):
3483 t.Fatal("timeout waiting for handler to get request")
3485 <-gotRes
3488 // Issue 11745.
3489 func TestTransportPrefersResponseOverWriteError(t *testing.T) {
3490 if testing.Short() {
3491 t.Skip("skipping in short mode")
3493 defer afterTest(t)
3494 const contentLengthLimit = 1024 * 1024 // 1MB
3495 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
3496 if r.ContentLength >= contentLengthLimit {
3497 w.WriteHeader(StatusBadRequest)
3498 r.Body.Close()
3499 return
3501 w.WriteHeader(StatusOK)
3503 defer ts.Close()
3504 c := ts.Client()
3506 fail := 0
3507 count := 100
3508 bigBody := strings.Repeat("a", contentLengthLimit*2)
3509 for i := 0; i < count; i++ {
3510 req, err := NewRequest("PUT", ts.URL, strings.NewReader(bigBody))
3511 if err != nil {
3512 t.Fatal(err)
3514 resp, err := c.Do(req)
3515 if err != nil {
3516 fail++
3517 t.Logf("%d = %#v", i, err)
3518 if ue, ok := err.(*url.Error); ok {
3519 t.Logf("urlErr = %#v", ue.Err)
3520 if ne, ok := ue.Err.(*net.OpError); ok {
3521 t.Logf("netOpError = %#v", ne.Err)
3524 } else {
3525 resp.Body.Close()
3526 if resp.StatusCode != 400 {
3527 t.Errorf("Expected status code 400, got %v", resp.Status)
3531 if fail > 0 {
3532 t.Errorf("Failed %v out of %v\n", fail, count)
3536 func TestTransportAutomaticHTTP2(t *testing.T) {
3537 testTransportAutoHTTP(t, &Transport{}, true)
3540 // golang.org/issue/14391: also check DefaultTransport
3541 func TestTransportAutomaticHTTP2_DefaultTransport(t *testing.T) {
3542 testTransportAutoHTTP(t, DefaultTransport.(*Transport), true)
3545 func TestTransportAutomaticHTTP2_TLSNextProto(t *testing.T) {
3546 testTransportAutoHTTP(t, &Transport{
3547 TLSNextProto: make(map[string]func(string, *tls.Conn) RoundTripper),
3548 }, false)
3551 func TestTransportAutomaticHTTP2_TLSConfig(t *testing.T) {
3552 testTransportAutoHTTP(t, &Transport{
3553 TLSClientConfig: new(tls.Config),
3554 }, false)
3557 func TestTransportAutomaticHTTP2_ExpectContinueTimeout(t *testing.T) {
3558 testTransportAutoHTTP(t, &Transport{
3559 ExpectContinueTimeout: 1 * time.Second,
3560 }, true)
3563 func TestTransportAutomaticHTTP2_Dial(t *testing.T) {
3564 var d net.Dialer
3565 testTransportAutoHTTP(t, &Transport{
3566 Dial: d.Dial,
3567 }, false)
3570 func TestTransportAutomaticHTTP2_DialTLS(t *testing.T) {
3571 testTransportAutoHTTP(t, &Transport{
3572 DialTLS: func(network, addr string) (net.Conn, error) {
3573 panic("unused")
3575 }, false)
3578 func testTransportAutoHTTP(t *testing.T, tr *Transport, wantH2 bool) {
3579 _, err := tr.RoundTrip(new(Request))
3580 if err == nil {
3581 t.Error("expected error from RoundTrip")
3583 if reg := tr.TLSNextProto["h2"] != nil; reg != wantH2 {
3584 t.Errorf("HTTP/2 registered = %v; want %v", reg, wantH2)
3588 // Issue 13633: there was a race where we returned bodyless responses
3589 // to callers before recycling the persistent connection, which meant
3590 // a client doing two subsequent requests could end up on different
3591 // connections. It's somewhat harmless but enough tests assume it's
3592 // not true in order to test other things that it's worth fixing.
3593 // Plus it's nice to be consistent and not have timing-dependent
3594 // behavior.
3595 func TestTransportReuseConnEmptyResponseBody(t *testing.T) {
3596 defer afterTest(t)
3597 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) {
3598 w.Header().Set("X-Addr", r.RemoteAddr)
3599 // Empty response body.
3601 defer cst.close()
3602 n := 100
3603 if testing.Short() {
3604 n = 10
3606 var firstAddr string
3607 for i := 0; i < n; i++ {
3608 res, err := cst.c.Get(cst.ts.URL)
3609 if err != nil {
3610 log.Fatal(err)
3612 addr := res.Header.Get("X-Addr")
3613 if i == 0 {
3614 firstAddr = addr
3615 } else if addr != firstAddr {
3616 t.Fatalf("On request %d, addr %q != original addr %q", i+1, addr, firstAddr)
3618 res.Body.Close()
3622 // Issue 13839
3623 func TestNoCrashReturningTransportAltConn(t *testing.T) {
3624 cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey)
3625 if err != nil {
3626 t.Fatal(err)
3628 ln := newLocalListener(t)
3629 defer ln.Close()
3631 handledPendingDial := make(chan bool, 1)
3632 SetPendingDialHooks(nil, func() { handledPendingDial <- true })
3633 defer SetPendingDialHooks(nil, nil)
3635 testDone := make(chan struct{})
3636 defer close(testDone)
3637 go func() {
3638 tln := tls.NewListener(ln, &tls.Config{
3639 NextProtos: []string{"foo"},
3640 Certificates: []tls.Certificate{cert},
3642 sc, err := tln.Accept()
3643 if err != nil {
3644 t.Error(err)
3645 return
3647 if err := sc.(*tls.Conn).Handshake(); err != nil {
3648 t.Error(err)
3649 return
3651 <-testDone
3652 sc.Close()
3655 addr := ln.Addr().String()
3657 req, _ := NewRequest("GET", "https://fake.tld/", nil)
3658 cancel := make(chan struct{})
3659 req.Cancel = cancel
3661 doReturned := make(chan bool, 1)
3662 madeRoundTripper := make(chan bool, 1)
3664 tr := &Transport{
3665 DisableKeepAlives: true,
3666 TLSNextProto: map[string]func(string, *tls.Conn) RoundTripper{
3667 "foo": func(authority string, c *tls.Conn) RoundTripper {
3668 madeRoundTripper <- true
3669 return funcRoundTripper(func() {
3670 t.Error("foo RoundTripper should not be called")
3674 Dial: func(_, _ string) (net.Conn, error) {
3675 panic("shouldn't be called")
3677 DialTLS: func(_, _ string) (net.Conn, error) {
3678 tc, err := tls.Dial("tcp", addr, &tls.Config{
3679 InsecureSkipVerify: true,
3680 NextProtos: []string{"foo"},
3682 if err != nil {
3683 return nil, err
3685 if err := tc.Handshake(); err != nil {
3686 return nil, err
3688 close(cancel)
3689 <-doReturned
3690 return tc, nil
3693 c := &Client{Transport: tr}
3695 _, err = c.Do(req)
3696 if ue, ok := err.(*url.Error); !ok || ue.Err != ExportErrRequestCanceledConn {
3697 t.Fatalf("Do error = %v; want url.Error with errRequestCanceledConn", err)
3700 doReturned <- true
3701 <-madeRoundTripper
3702 <-handledPendingDial
3705 func TestTransportReuseConnection_Gzip_Chunked(t *testing.T) {
3706 testTransportReuseConnection_Gzip(t, true)
3709 func TestTransportReuseConnection_Gzip_ContentLength(t *testing.T) {
3710 testTransportReuseConnection_Gzip(t, false)
3713 // Make sure we re-use underlying TCP connection for gzipped responses too.
3714 func testTransportReuseConnection_Gzip(t *testing.T, chunked bool) {
3715 setParallel(t)
3716 defer afterTest(t)
3717 addr := make(chan string, 2)
3718 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
3719 addr <- r.RemoteAddr
3720 w.Header().Set("Content-Encoding", "gzip")
3721 if chunked {
3722 w.(Flusher).Flush()
3724 w.Write(rgz) // arbitrary gzip response
3726 defer ts.Close()
3727 c := ts.Client()
3729 for i := 0; i < 2; i++ {
3730 res, err := c.Get(ts.URL)
3731 if err != nil {
3732 t.Fatal(err)
3734 buf := make([]byte, len(rgz))
3735 if n, err := io.ReadFull(res.Body, buf); err != nil {
3736 t.Errorf("%d. ReadFull = %v, %v", i, n, err)
3738 // Note: no res.Body.Close call. It should work without it,
3739 // since the flate.Reader's internal buffering will hit EOF
3740 // and that should be sufficient.
3742 a1, a2 := <-addr, <-addr
3743 if a1 != a2 {
3744 t.Fatalf("didn't reuse connection")
3748 func TestTransportResponseHeaderLength(t *testing.T) {
3749 setParallel(t)
3750 defer afterTest(t)
3751 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
3752 if r.URL.Path == "/long" {
3753 w.Header().Set("Long", strings.Repeat("a", 1<<20))
3756 defer ts.Close()
3757 c := ts.Client()
3758 c.Transport.(*Transport).MaxResponseHeaderBytes = 512 << 10
3760 if res, err := c.Get(ts.URL); err != nil {
3761 t.Fatal(err)
3762 } else {
3763 res.Body.Close()
3766 res, err := c.Get(ts.URL + "/long")
3767 if err == nil {
3768 defer res.Body.Close()
3769 var n int64
3770 for k, vv := range res.Header {
3771 for _, v := range vv {
3772 n += int64(len(k)) + int64(len(v))
3775 t.Fatalf("Unexpected success. Got %v and %d bytes of response headers", res.Status, n)
3777 if want := "server response headers exceeded 524288 bytes"; !strings.Contains(err.Error(), want) {
3778 t.Errorf("got error: %v; want %q", err, want)
3782 func TestTransportEventTrace(t *testing.T) { testTransportEventTrace(t, h1Mode, false) }
3783 func TestTransportEventTrace_h2(t *testing.T) { testTransportEventTrace(t, h2Mode, false) }
3785 // test a non-nil httptrace.ClientTrace but with all hooks set to zero.
3786 func TestTransportEventTrace_NoHooks(t *testing.T) { testTransportEventTrace(t, h1Mode, true) }
3787 func TestTransportEventTrace_NoHooks_h2(t *testing.T) { testTransportEventTrace(t, h2Mode, true) }
3789 func testTransportEventTrace(t *testing.T, h2 bool, noHooks bool) {
3790 defer afterTest(t)
3791 const resBody = "some body"
3792 gotWroteReqEvent := make(chan struct{}, 500)
3793 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
3794 if r.Method == "GET" {
3795 // Do nothing for the second request.
3796 return
3798 if _, err := ioutil.ReadAll(r.Body); err != nil {
3799 t.Error(err)
3801 if !noHooks {
3802 select {
3803 case <-gotWroteReqEvent:
3804 case <-time.After(5 * time.Second):
3805 t.Error("timeout waiting for WroteRequest event")
3808 io.WriteString(w, resBody)
3810 defer cst.close()
3812 cst.tr.ExpectContinueTimeout = 1 * time.Second
3814 var mu sync.Mutex // guards buf
3815 var buf bytes.Buffer
3816 logf := func(format string, args ...interface{}) {
3817 mu.Lock()
3818 defer mu.Unlock()
3819 fmt.Fprintf(&buf, format, args...)
3820 buf.WriteByte('\n')
3823 addrStr := cst.ts.Listener.Addr().String()
3824 ip, port, err := net.SplitHostPort(addrStr)
3825 if err != nil {
3826 t.Fatal(err)
3829 // Install a fake DNS server.
3830 ctx := context.WithValue(context.Background(), nettrace.LookupIPAltResolverKey{}, func(ctx context.Context, host string) ([]net.IPAddr, error) {
3831 if host != "dns-is-faked.golang" {
3832 t.Errorf("unexpected DNS host lookup for %q", host)
3833 return nil, nil
3835 return []net.IPAddr{{IP: net.ParseIP(ip)}}, nil
3838 body := "some body"
3839 req, _ := NewRequest("POST", cst.scheme()+"://dns-is-faked.golang:"+port, strings.NewReader(body))
3840 req.Header["X-Foo-Multiple-Vals"] = []string{"bar", "baz"}
3841 trace := &httptrace.ClientTrace{
3842 GetConn: func(hostPort string) { logf("Getting conn for %v ...", hostPort) },
3843 GotConn: func(ci httptrace.GotConnInfo) { logf("got conn: %+v", ci) },
3844 GotFirstResponseByte: func() { logf("first response byte") },
3845 PutIdleConn: func(err error) { logf("PutIdleConn = %v", err) },
3846 DNSStart: func(e httptrace.DNSStartInfo) { logf("DNS start: %+v", e) },
3847 DNSDone: func(e httptrace.DNSDoneInfo) { logf("DNS done: %+v", e) },
3848 ConnectStart: func(network, addr string) { logf("ConnectStart: Connecting to %s %s ...", network, addr) },
3849 ConnectDone: func(network, addr string, err error) {
3850 if err != nil {
3851 t.Errorf("ConnectDone: %v", err)
3853 logf("ConnectDone: connected to %s %s = %v", network, addr, err)
3855 WroteHeaderField: func(key string, value []string) {
3856 logf("WroteHeaderField: %s: %v", key, value)
3858 WroteHeaders: func() {
3859 logf("WroteHeaders")
3861 Wait100Continue: func() { logf("Wait100Continue") },
3862 Got100Continue: func() { logf("Got100Continue") },
3863 WroteRequest: func(e httptrace.WroteRequestInfo) {
3864 logf("WroteRequest: %+v", e)
3865 gotWroteReqEvent <- struct{}{}
3868 if h2 {
3869 trace.TLSHandshakeStart = func() { logf("tls handshake start") }
3870 trace.TLSHandshakeDone = func(s tls.ConnectionState, err error) {
3871 logf("tls handshake done. ConnectionState = %v \n err = %v", s, err)
3874 if noHooks {
3875 // zero out all func pointers, trying to get some path to crash
3876 *trace = httptrace.ClientTrace{}
3878 req = req.WithContext(httptrace.WithClientTrace(ctx, trace))
3880 req.Header.Set("Expect", "100-continue")
3881 res, err := cst.c.Do(req)
3882 if err != nil {
3883 t.Fatal(err)
3885 logf("got roundtrip.response")
3886 slurp, err := ioutil.ReadAll(res.Body)
3887 if err != nil {
3888 t.Fatal(err)
3890 logf("consumed body")
3891 if string(slurp) != resBody || res.StatusCode != 200 {
3892 t.Fatalf("Got %q, %v; want %q, 200 OK", slurp, res.Status, resBody)
3894 res.Body.Close()
3896 if noHooks {
3897 // Done at this point. Just testing a full HTTP
3898 // requests can happen with a trace pointing to a zero
3899 // ClientTrace, full of nil func pointers.
3900 return
3903 mu.Lock()
3904 got := buf.String()
3905 mu.Unlock()
3907 wantOnce := func(sub string) {
3908 if strings.Count(got, sub) != 1 {
3909 t.Errorf("expected substring %q exactly once in output.", sub)
3912 wantOnceOrMore := func(sub string) {
3913 if strings.Count(got, sub) == 0 {
3914 t.Errorf("expected substring %q at least once in output.", sub)
3917 wantOnce("Getting conn for dns-is-faked.golang:" + port)
3918 wantOnce("DNS start: {Host:dns-is-faked.golang}")
3919 wantOnce("DNS done: {Addrs:[{IP:" + ip + " Zone:}] Err:<nil> Coalesced:false}")
3920 wantOnce("got conn: {")
3921 wantOnceOrMore("Connecting to tcp " + addrStr)
3922 wantOnceOrMore("connected to tcp " + addrStr + " = <nil>")
3923 wantOnce("Reused:false WasIdle:false IdleTime:0s")
3924 wantOnce("first response byte")
3925 if h2 {
3926 wantOnce("tls handshake start")
3927 wantOnce("tls handshake done")
3928 } else {
3929 wantOnce("PutIdleConn = <nil>")
3930 wantOnce("WroteHeaderField: User-Agent: [Go-http-client/1.1]")
3931 // TODO(meirf): issue 19761. Make these agnostic to h1/h2. (These are not h1 specific, but the
3932 // WroteHeaderField hook is not yet implemented in h2.)
3933 wantOnce(fmt.Sprintf("WroteHeaderField: Host: [dns-is-faked.golang:%s]", port))
3934 wantOnce(fmt.Sprintf("WroteHeaderField: Content-Length: [%d]", len(body)))
3935 wantOnce("WroteHeaderField: X-Foo-Multiple-Vals: [bar baz]")
3936 wantOnce("WroteHeaderField: Accept-Encoding: [gzip]")
3938 wantOnce("WroteHeaders")
3939 wantOnce("Wait100Continue")
3940 wantOnce("Got100Continue")
3941 wantOnce("WroteRequest: {Err:<nil>}")
3942 if strings.Contains(got, " to udp ") {
3943 t.Errorf("should not see UDP (DNS) connections")
3945 if t.Failed() {
3946 t.Errorf("Output:\n%s", got)
3949 // And do a second request:
3950 req, _ = NewRequest("GET", cst.scheme()+"://dns-is-faked.golang:"+port, nil)
3951 req = req.WithContext(httptrace.WithClientTrace(ctx, trace))
3952 res, err = cst.c.Do(req)
3953 if err != nil {
3954 t.Fatal(err)
3956 if res.StatusCode != 200 {
3957 t.Fatal(res.Status)
3959 res.Body.Close()
3961 mu.Lock()
3962 got = buf.String()
3963 mu.Unlock()
3965 sub := "Getting conn for dns-is-faked.golang:"
3966 if gotn, want := strings.Count(got, sub), 2; gotn != want {
3967 t.Errorf("substring %q appeared %d times; want %d. Log:\n%s", sub, gotn, want, got)
3972 func TestTransportEventTraceTLSVerify(t *testing.T) {
3973 var mu sync.Mutex
3974 var buf bytes.Buffer
3975 logf := func(format string, args ...interface{}) {
3976 mu.Lock()
3977 defer mu.Unlock()
3978 fmt.Fprintf(&buf, format, args...)
3979 buf.WriteByte('\n')
3982 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
3983 t.Error("Unexpected request")
3985 defer ts.Close()
3986 ts.Config.ErrorLog = log.New(funcWriter(func(p []byte) (int, error) {
3987 logf("%s", p)
3988 return len(p), nil
3989 }), "", 0)
3991 certpool := x509.NewCertPool()
3992 certpool.AddCert(ts.Certificate())
3994 c := &Client{Transport: &Transport{
3995 TLSClientConfig: &tls.Config{
3996 ServerName: "dns-is-faked.golang",
3997 RootCAs: certpool,
4001 trace := &httptrace.ClientTrace{
4002 TLSHandshakeStart: func() { logf("TLSHandshakeStart") },
4003 TLSHandshakeDone: func(s tls.ConnectionState, err error) {
4004 logf("TLSHandshakeDone: ConnectionState = %v \n err = %v", s, err)
4008 req, _ := NewRequest("GET", ts.URL, nil)
4009 req = req.WithContext(httptrace.WithClientTrace(context.Background(), trace))
4010 _, err := c.Do(req)
4011 if err == nil {
4012 t.Error("Expected request to fail TLS verification")
4015 mu.Lock()
4016 got := buf.String()
4017 mu.Unlock()
4019 wantOnce := func(sub string) {
4020 if strings.Count(got, sub) != 1 {
4021 t.Errorf("expected substring %q exactly once in output.", sub)
4025 wantOnce("TLSHandshakeStart")
4026 wantOnce("TLSHandshakeDone")
4027 wantOnce("err = x509: certificate is valid for example.com")
4029 if t.Failed() {
4030 t.Errorf("Output:\n%s", got)
4034 var (
4035 isDNSHijackedOnce sync.Once
4036 isDNSHijacked bool
4039 func skipIfDNSHijacked(t *testing.T) {
4040 // Skip this test if the user is using a shady/ISP
4041 // DNS server hijacking queries.
4042 // See issues 16732, 16716.
4043 isDNSHijackedOnce.Do(func() {
4044 addrs, _ := net.LookupHost("dns-should-not-resolve.golang")
4045 isDNSHijacked = len(addrs) != 0
4047 if isDNSHijacked {
4048 t.Skip("skipping; test requires non-hijacking DNS server")
4052 func TestTransportEventTraceRealDNS(t *testing.T) {
4053 skipIfDNSHijacked(t)
4054 defer afterTest(t)
4055 tr := &Transport{}
4056 defer tr.CloseIdleConnections()
4057 c := &Client{Transport: tr}
4059 var mu sync.Mutex // guards buf
4060 var buf bytes.Buffer
4061 logf := func(format string, args ...interface{}) {
4062 mu.Lock()
4063 defer mu.Unlock()
4064 fmt.Fprintf(&buf, format, args...)
4065 buf.WriteByte('\n')
4068 req, _ := NewRequest("GET", "http://dns-should-not-resolve.golang:80", nil)
4069 trace := &httptrace.ClientTrace{
4070 DNSStart: func(e httptrace.DNSStartInfo) { logf("DNSStart: %+v", e) },
4071 DNSDone: func(e httptrace.DNSDoneInfo) { logf("DNSDone: %+v", e) },
4072 ConnectStart: func(network, addr string) { logf("ConnectStart: %s %s", network, addr) },
4073 ConnectDone: func(network, addr string, err error) { logf("ConnectDone: %s %s %v", network, addr, err) },
4075 req = req.WithContext(httptrace.WithClientTrace(context.Background(), trace))
4077 resp, err := c.Do(req)
4078 if err == nil {
4079 resp.Body.Close()
4080 t.Fatal("expected error during DNS lookup")
4083 mu.Lock()
4084 got := buf.String()
4085 mu.Unlock()
4087 wantSub := func(sub string) {
4088 if !strings.Contains(got, sub) {
4089 t.Errorf("expected substring %q in output.", sub)
4092 wantSub("DNSStart: {Host:dns-should-not-resolve.golang}")
4093 wantSub("DNSDone: {Addrs:[] Err:")
4094 if strings.Contains(got, "ConnectStart") || strings.Contains(got, "ConnectDone") {
4095 t.Errorf("should not see Connect events")
4097 if t.Failed() {
4098 t.Errorf("Output:\n%s", got)
4102 // Issue 14353: port can only contain digits.
4103 func TestTransportRejectsAlphaPort(t *testing.T) {
4104 res, err := Get("http://dummy.tld:123foo/bar")
4105 if err == nil {
4106 res.Body.Close()
4107 t.Fatal("unexpected success")
4109 ue, ok := err.(*url.Error)
4110 if !ok {
4111 t.Fatalf("got %#v; want *url.Error", err)
4113 got := ue.Err.Error()
4114 want := `invalid URL port "123foo"`
4115 if got != want {
4116 t.Errorf("got error %q; want %q", got, want)
4120 // Test the httptrace.TLSHandshake{Start,Done} hooks with a https http1
4121 // connections. The http2 test is done in TestTransportEventTrace_h2
4122 func TestTLSHandshakeTrace(t *testing.T) {
4123 defer afterTest(t)
4124 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
4125 defer ts.Close()
4127 var mu sync.Mutex
4128 var start, done bool
4129 trace := &httptrace.ClientTrace{
4130 TLSHandshakeStart: func() {
4131 mu.Lock()
4132 defer mu.Unlock()
4133 start = true
4135 TLSHandshakeDone: func(s tls.ConnectionState, err error) {
4136 mu.Lock()
4137 defer mu.Unlock()
4138 done = true
4139 if err != nil {
4140 t.Fatal("Expected error to be nil but was:", err)
4145 c := ts.Client()
4146 req, err := NewRequest("GET", ts.URL, nil)
4147 if err != nil {
4148 t.Fatal("Unable to construct test request:", err)
4150 req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
4152 r, err := c.Do(req)
4153 if err != nil {
4154 t.Fatal("Unexpected error making request:", err)
4156 r.Body.Close()
4157 mu.Lock()
4158 defer mu.Unlock()
4159 if !start {
4160 t.Fatal("Expected TLSHandshakeStart to be called, but wasn't")
4162 if !done {
4163 t.Fatal("Expected TLSHandshakeDone to be called, but wasnt't")
4167 func TestTransportMaxIdleConns(t *testing.T) {
4168 defer afterTest(t)
4169 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
4170 // No body for convenience.
4172 defer ts.Close()
4173 c := ts.Client()
4174 tr := c.Transport.(*Transport)
4175 tr.MaxIdleConns = 4
4177 ip, port, err := net.SplitHostPort(ts.Listener.Addr().String())
4178 if err != nil {
4179 t.Fatal(err)
4181 ctx := context.WithValue(context.Background(), nettrace.LookupIPAltResolverKey{}, func(ctx context.Context, host string) ([]net.IPAddr, error) {
4182 return []net.IPAddr{{IP: net.ParseIP(ip)}}, nil
4185 hitHost := func(n int) {
4186 req, _ := NewRequest("GET", fmt.Sprintf("http://host-%d.dns-is-faked.golang:"+port, n), nil)
4187 req = req.WithContext(ctx)
4188 res, err := c.Do(req)
4189 if err != nil {
4190 t.Fatal(err)
4192 res.Body.Close()
4194 for i := 0; i < 4; i++ {
4195 hitHost(i)
4197 want := []string{
4198 "|http|host-0.dns-is-faked.golang:" + port,
4199 "|http|host-1.dns-is-faked.golang:" + port,
4200 "|http|host-2.dns-is-faked.golang:" + port,
4201 "|http|host-3.dns-is-faked.golang:" + port,
4203 if got := tr.IdleConnKeysForTesting(); !reflect.DeepEqual(got, want) {
4204 t.Fatalf("idle conn keys mismatch.\n got: %q\nwant: %q\n", got, want)
4207 // Now hitting the 5th host should kick out the first host:
4208 hitHost(4)
4209 want = []string{
4210 "|http|host-1.dns-is-faked.golang:" + port,
4211 "|http|host-2.dns-is-faked.golang:" + port,
4212 "|http|host-3.dns-is-faked.golang:" + port,
4213 "|http|host-4.dns-is-faked.golang:" + port,
4215 if got := tr.IdleConnKeysForTesting(); !reflect.DeepEqual(got, want) {
4216 t.Fatalf("idle conn keys mismatch after 5th host.\n got: %q\nwant: %q\n", got, want)
4220 func TestTransportIdleConnTimeout_h1(t *testing.T) { testTransportIdleConnTimeout(t, h1Mode) }
4221 func TestTransportIdleConnTimeout_h2(t *testing.T) { testTransportIdleConnTimeout(t, h2Mode) }
4222 func testTransportIdleConnTimeout(t *testing.T, h2 bool) {
4223 if testing.Short() {
4224 t.Skip("skipping in short mode")
4226 defer afterTest(t)
4228 const timeout = 1 * time.Second
4230 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
4231 // No body for convenience.
4233 defer cst.close()
4234 tr := cst.tr
4235 tr.IdleConnTimeout = timeout
4236 defer tr.CloseIdleConnections()
4237 c := &Client{Transport: tr}
4239 idleConns := func() []string {
4240 if h2 {
4241 return tr.IdleConnStrsForTesting_h2()
4242 } else {
4243 return tr.IdleConnStrsForTesting()
4247 var conn string
4248 doReq := func(n int) {
4249 req, _ := NewRequest("GET", cst.ts.URL, nil)
4250 req = req.WithContext(httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{
4251 PutIdleConn: func(err error) {
4252 if err != nil {
4253 t.Errorf("failed to keep idle conn: %v", err)
4257 res, err := c.Do(req)
4258 if err != nil {
4259 t.Fatal(err)
4261 res.Body.Close()
4262 conns := idleConns()
4263 if len(conns) != 1 {
4264 t.Fatalf("req %v: unexpected number of idle conns: %q", n, conns)
4266 if conn == "" {
4267 conn = conns[0]
4269 if conn != conns[0] {
4270 t.Fatalf("req %v: cached connection changed; expected the same one throughout the test", n)
4273 for i := 0; i < 3; i++ {
4274 doReq(i)
4275 time.Sleep(timeout / 2)
4277 time.Sleep(timeout * 3 / 2)
4278 if got := idleConns(); len(got) != 0 {
4279 t.Errorf("idle conns = %q; want none", got)
4283 // Issue 16208: Go 1.7 crashed after Transport.IdleConnTimeout if an
4284 // HTTP/2 connection was established but but its caller no longer
4285 // wanted it. (Assuming the connection cache was enabled, which it is
4286 // by default)
4288 // This test reproduced the crash by setting the IdleConnTimeout low
4289 // (to make the test reasonable) and then making a request which is
4290 // canceled by the DialTLS hook, which then also waits to return the
4291 // real connection until after the RoundTrip saw the error. Then we
4292 // know the successful tls.Dial from DialTLS will need to go into the
4293 // idle pool. Then we give it a of time to explode.
4294 func TestIdleConnH2Crash(t *testing.T) {
4295 setParallel(t)
4296 cst := newClientServerTest(t, h2Mode, HandlerFunc(func(w ResponseWriter, r *Request) {
4297 // nothing
4299 defer cst.close()
4301 ctx, cancel := context.WithCancel(context.Background())
4302 defer cancel()
4304 sawDoErr := make(chan bool, 1)
4305 testDone := make(chan struct{})
4306 defer close(testDone)
4308 cst.tr.IdleConnTimeout = 5 * time.Millisecond
4309 cst.tr.DialTLS = func(network, addr string) (net.Conn, error) {
4310 c, err := tls.Dial(network, addr, &tls.Config{
4311 InsecureSkipVerify: true,
4312 NextProtos: []string{"h2"},
4314 if err != nil {
4315 t.Error(err)
4316 return nil, err
4318 if cs := c.ConnectionState(); cs.NegotiatedProtocol != "h2" {
4319 t.Errorf("protocol = %q; want %q", cs.NegotiatedProtocol, "h2")
4320 c.Close()
4321 return nil, errors.New("bogus")
4324 cancel()
4326 failTimer := time.NewTimer(5 * time.Second)
4327 defer failTimer.Stop()
4328 select {
4329 case <-sawDoErr:
4330 case <-testDone:
4331 case <-failTimer.C:
4332 t.Error("timeout in DialTLS, waiting too long for cst.c.Do to fail")
4334 return c, nil
4337 req, _ := NewRequest("GET", cst.ts.URL, nil)
4338 req = req.WithContext(ctx)
4339 res, err := cst.c.Do(req)
4340 if err == nil {
4341 res.Body.Close()
4342 t.Fatal("unexpected success")
4344 sawDoErr <- true
4346 // Wait for the explosion.
4347 time.Sleep(cst.tr.IdleConnTimeout * 10)
4350 type funcConn struct {
4351 net.Conn
4352 read func([]byte) (int, error)
4353 write func([]byte) (int, error)
4356 func (c funcConn) Read(p []byte) (int, error) { return c.read(p) }
4357 func (c funcConn) Write(p []byte) (int, error) { return c.write(p) }
4358 func (c funcConn) Close() error { return nil }
4360 // Issue 16465: Transport.RoundTrip should return the raw net.Conn.Read error from Peek
4361 // back to the caller.
4362 func TestTransportReturnsPeekError(t *testing.T) {
4363 errValue := errors.New("specific error value")
4365 wrote := make(chan struct{})
4366 var wroteOnce sync.Once
4368 tr := &Transport{
4369 Dial: func(network, addr string) (net.Conn, error) {
4370 c := funcConn{
4371 read: func([]byte) (int, error) {
4372 <-wrote
4373 return 0, errValue
4375 write: func(p []byte) (int, error) {
4376 wroteOnce.Do(func() { close(wrote) })
4377 return len(p), nil
4380 return c, nil
4383 _, err := tr.RoundTrip(httptest.NewRequest("GET", "http://fake.tld/", nil))
4384 if err != errValue {
4385 t.Errorf("error = %#v; want %v", err, errValue)
4389 // Issue 13835: international domain names should work
4390 func TestTransportIDNA_h1(t *testing.T) { testTransportIDNA(t, h1Mode) }
4391 func TestTransportIDNA_h2(t *testing.T) { testTransportIDNA(t, h2Mode) }
4392 func testTransportIDNA(t *testing.T, h2 bool) {
4393 defer afterTest(t)
4395 const uniDomain = "гофер.го"
4396 const punyDomain = "xn--c1ae0ajs.xn--c1aw"
4398 var port string
4399 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
4400 want := punyDomain + ":" + port
4401 if r.Host != want {
4402 t.Errorf("Host header = %q; want %q", r.Host, want)
4404 if h2 {
4405 if r.TLS == nil {
4406 t.Errorf("r.TLS == nil")
4407 } else if r.TLS.ServerName != punyDomain {
4408 t.Errorf("TLS.ServerName = %q; want %q", r.TLS.ServerName, punyDomain)
4411 w.Header().Set("Hit-Handler", "1")
4413 defer cst.close()
4415 ip, port, err := net.SplitHostPort(cst.ts.Listener.Addr().String())
4416 if err != nil {
4417 t.Fatal(err)
4420 // Install a fake DNS server.
4421 ctx := context.WithValue(context.Background(), nettrace.LookupIPAltResolverKey{}, func(ctx context.Context, host string) ([]net.IPAddr, error) {
4422 if host != punyDomain {
4423 t.Errorf("got DNS host lookup for %q; want %q", host, punyDomain)
4424 return nil, nil
4426 return []net.IPAddr{{IP: net.ParseIP(ip)}}, nil
4429 req, _ := NewRequest("GET", cst.scheme()+"://"+uniDomain+":"+port, nil)
4430 trace := &httptrace.ClientTrace{
4431 GetConn: func(hostPort string) {
4432 want := net.JoinHostPort(punyDomain, port)
4433 if hostPort != want {
4434 t.Errorf("getting conn for %q; want %q", hostPort, want)
4437 DNSStart: func(e httptrace.DNSStartInfo) {
4438 if e.Host != punyDomain {
4439 t.Errorf("DNSStart Host = %q; want %q", e.Host, punyDomain)
4443 req = req.WithContext(httptrace.WithClientTrace(ctx, trace))
4445 res, err := cst.tr.RoundTrip(req)
4446 if err != nil {
4447 t.Fatal(err)
4449 defer res.Body.Close()
4450 if res.Header.Get("Hit-Handler") != "1" {
4451 out, err := httputil.DumpResponse(res, true)
4452 if err != nil {
4453 t.Fatal(err)
4455 t.Errorf("Response body wasn't from Handler. Got:\n%s\n", out)
4459 // Issue 13290: send User-Agent in proxy CONNECT
4460 func TestTransportProxyConnectHeader(t *testing.T) {
4461 defer afterTest(t)
4462 reqc := make(chan *Request, 1)
4463 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
4464 if r.Method != "CONNECT" {
4465 t.Errorf("method = %q; want CONNECT", r.Method)
4467 reqc <- r
4468 c, _, err := w.(Hijacker).Hijack()
4469 if err != nil {
4470 t.Errorf("Hijack: %v", err)
4471 return
4473 c.Close()
4475 defer ts.Close()
4477 c := ts.Client()
4478 c.Transport.(*Transport).Proxy = func(r *Request) (*url.URL, error) {
4479 return url.Parse(ts.URL)
4481 c.Transport.(*Transport).ProxyConnectHeader = Header{
4482 "User-Agent": {"foo"},
4483 "Other": {"bar"},
4486 res, err := c.Get("https://dummy.tld/") // https to force a CONNECT
4487 if err == nil {
4488 res.Body.Close()
4489 t.Errorf("unexpected success")
4491 select {
4492 case <-time.After(3 * time.Second):
4493 t.Fatal("timeout")
4494 case r := <-reqc:
4495 if got, want := r.Header.Get("User-Agent"), "foo"; got != want {
4496 t.Errorf("CONNECT request User-Agent = %q; want %q", got, want)
4498 if got, want := r.Header.Get("Other"), "bar"; got != want {
4499 t.Errorf("CONNECT request Other = %q; want %q", got, want)
4504 var errFakeRoundTrip = errors.New("fake roundtrip")
4506 type funcRoundTripper func()
4508 func (fn funcRoundTripper) RoundTrip(*Request) (*Response, error) {
4509 fn()
4510 return nil, errFakeRoundTrip
4513 func wantBody(res *Response, err error, want string) error {
4514 if err != nil {
4515 return err
4517 slurp, err := ioutil.ReadAll(res.Body)
4518 if err != nil {
4519 return fmt.Errorf("error reading body: %v", err)
4521 if string(slurp) != want {
4522 return fmt.Errorf("body = %q; want %q", slurp, want)
4524 if err := res.Body.Close(); err != nil {
4525 return fmt.Errorf("body Close = %v", err)
4527 return nil
4530 func newLocalListener(t *testing.T) net.Listener {
4531 ln, err := net.Listen("tcp", "127.0.0.1:0")
4532 if err != nil {
4533 ln, err = net.Listen("tcp6", "[::1]:0")
4535 if err != nil {
4536 t.Fatal(err)
4538 return ln
4541 type countCloseReader struct {
4542 n *int
4543 io.Reader
4546 func (cr countCloseReader) Close() error {
4547 (*cr.n)++
4548 return nil
4551 // rgz is a gzip quine that uncompresses to itself.
4552 var rgz = []byte{
4553 0x1f, 0x8b, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
4554 0x00, 0x00, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73,
4555 0x69, 0x76, 0x65, 0x00, 0x92, 0xef, 0xe6, 0xe0,
4556 0x60, 0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2,
4557 0xe2, 0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17,
4558 0x00, 0xe8, 0xff, 0x92, 0xef, 0xe6, 0xe0, 0x60,
4559 0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2, 0xe2,
4560 0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17, 0x00,
4561 0xe8, 0xff, 0x42, 0x12, 0x46, 0x16, 0x06, 0x00,
4562 0x05, 0x00, 0xfa, 0xff, 0x42, 0x12, 0x46, 0x16,
4563 0x06, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00, 0x05,
4564 0x00, 0xfa, 0xff, 0x00, 0x14, 0x00, 0xeb, 0xff,
4565 0x42, 0x12, 0x46, 0x16, 0x06, 0x00, 0x05, 0x00,
4566 0xfa, 0xff, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00,
4567 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4,
4568 0x00, 0x00, 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88,
4569 0x21, 0xc4, 0x00, 0x00, 0x14, 0x00, 0xeb, 0xff,
4570 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x14, 0x00,
4571 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00,
4572 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4,
4573 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4574 0x00, 0xff, 0xff, 0x00, 0x17, 0x00, 0xe8, 0xff,
4575 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x00, 0x00,
4576 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
4577 0x17, 0x00, 0xe8, 0xff, 0x42, 0x12, 0x46, 0x16,
4578 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08,
4579 0x00, 0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa,
4580 0x00, 0x00, 0x00, 0x42, 0x12, 0x46, 0x16, 0x06,
4581 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08, 0x00,
4582 0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00,
4583 0x00, 0x00, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00,
4584 0x00, 0x00,
4587 // Ensure that a missing status doesn't make the server panic
4588 // See Issue https://golang.org/issues/21701
4589 func TestMissingStatusNoPanic(t *testing.T) {
4590 t.Parallel()
4592 const want = "unknown status code"
4594 ln := newLocalListener(t)
4595 addr := ln.Addr().String()
4596 shutdown := make(chan bool, 1)
4597 done := make(chan bool)
4598 fullAddrURL := fmt.Sprintf("http://%s", addr)
4599 raw := "HTTP/1.1 400\r\n" +
4600 "Date: Wed, 30 Aug 2017 19:09:27 GMT\r\n" +
4601 "Content-Type: text/html; charset=utf-8\r\n" +
4602 "Content-Length: 10\r\n" +
4603 "Last-Modified: Wed, 30 Aug 2017 19:02:02 GMT\r\n" +
4604 "Vary: Accept-Encoding\r\n\r\n" +
4605 "Aloha Olaa"
4607 go func() {
4608 defer func() {
4609 ln.Close()
4610 close(done)
4613 conn, _ := ln.Accept()
4614 if conn != nil {
4615 io.WriteString(conn, raw)
4616 ioutil.ReadAll(conn)
4617 conn.Close()
4621 proxyURL, err := url.Parse(fullAddrURL)
4622 if err != nil {
4623 t.Fatalf("proxyURL: %v", err)
4626 tr := &Transport{Proxy: ProxyURL(proxyURL)}
4628 req, _ := NewRequest("GET", "https://golang.org/", nil)
4629 res, err, panicked := doFetchCheckPanic(tr, req)
4630 if panicked {
4631 t.Error("panicked, expecting an error")
4633 if res != nil && res.Body != nil {
4634 io.Copy(ioutil.Discard, res.Body)
4635 res.Body.Close()
4638 if err == nil || !strings.Contains(err.Error(), want) {
4639 t.Errorf("got=%v want=%q", err, want)
4642 close(shutdown)
4643 <-done
4646 func doFetchCheckPanic(tr *Transport, req *Request) (res *Response, err error, panicked bool) {
4647 defer func() {
4648 if r := recover(); r != nil {
4649 panicked = true
4652 res, err = tr.RoundTrip(req)
4653 return
4656 // Issue 22330: do not allow the response body to be read when the status code
4657 // forbids a response body.
4658 func TestNoBodyOnChunked304Response(t *testing.T) {
4659 defer afterTest(t)
4660 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) {
4661 conn, buf, _ := w.(Hijacker).Hijack()
4662 buf.Write([]byte("HTTP/1.1 304 NOT MODIFIED\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\n"))
4663 buf.Flush()
4664 conn.Close()
4666 defer cst.close()
4668 // Our test server above is sending back bogus data after the
4669 // response (the "0\r\n\r\n" part), which causes the Transport
4670 // code to log spam. Disable keep-alives so we never even try
4671 // to reuse the connection.
4672 cst.tr.DisableKeepAlives = true
4674 res, err := cst.c.Get(cst.ts.URL)
4675 if err != nil {
4676 t.Fatal(err)
4679 if res.Body != NoBody {
4680 t.Errorf("Unexpected body on 304 response")
4684 type funcWriter func([]byte) (int, error)
4686 func (f funcWriter) Write(p []byte) (int, error) { return f(p) }
4688 type doneContext struct {
4689 context.Context
4690 err error
4693 func (doneContext) Done() <-chan struct{} {
4694 c := make(chan struct{})
4695 close(c)
4696 return c
4699 func (d doneContext) Err() error { return d.err }
4701 // Issue 25852: Transport should check whether Context is done early.
4702 func TestTransportCheckContextDoneEarly(t *testing.T) {
4703 tr := &Transport{}
4704 req, _ := NewRequest("GET", "http://fake.example/", nil)
4705 wantErr := errors.New("some error")
4706 req = req.WithContext(doneContext{context.Background(), wantErr})
4707 _, err := tr.RoundTrip(req)
4708 if err != wantErr {
4709 t.Errorf("error = %v; want %v", err, wantErr)
4713 // Issue 23399: verify that if a client request times out, the Transport's
4714 // conn is closed so that it's not reused.
4716 // This is the test variant that times out before the server replies with
4717 // any response headers.
4718 func TestClientTimeoutKillsConn_BeforeHeaders(t *testing.T) {
4719 setParallel(t)
4720 defer afterTest(t)
4721 inHandler := make(chan net.Conn, 1)
4722 handlerReadReturned := make(chan bool, 1)
4723 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) {
4724 conn, _, err := w.(Hijacker).Hijack()
4725 if err != nil {
4726 t.Error(err)
4727 return
4729 inHandler <- conn
4730 n, err := conn.Read([]byte{0})
4731 if n != 0 || err != io.EOF {
4732 t.Errorf("unexpected Read result: %v, %v", n, err)
4734 handlerReadReturned <- true
4736 defer cst.close()
4738 const timeout = 50 * time.Millisecond
4739 cst.c.Timeout = timeout
4741 _, err := cst.c.Get(cst.ts.URL)
4742 if err == nil {
4743 t.Fatal("unexpected Get succeess")
4746 select {
4747 case c := <-inHandler:
4748 select {
4749 case <-handlerReadReturned:
4750 // Success.
4751 return
4752 case <-time.After(5 * time.Second):
4753 t.Error("Handler's conn.Read seems to be stuck in Read")
4754 c.Close() // close it to unblock Handler
4756 case <-time.After(timeout * 10):
4757 // If we didn't get into the Handler in 50ms, that probably means
4758 // the builder was just slow and the the Get failed in that time
4759 // but never made it to the server. That's fine. We'll usually
4760 // test the part above on faster machines.
4761 t.Skip("skipping test on slow builder")
4765 // Issue 23399: verify that if a client request times out, the Transport's
4766 // conn is closed so that it's not reused.
4768 // This is the test variant that has the server send response headers
4769 // first, and time out during the the write of the response body.
4770 func TestClientTimeoutKillsConn_AfterHeaders(t *testing.T) {
4771 setParallel(t)
4772 defer afterTest(t)
4773 inHandler := make(chan net.Conn, 1)
4774 handlerResult := make(chan error, 1)
4775 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) {
4776 w.Header().Set("Content-Length", "100")
4777 w.(Flusher).Flush()
4778 conn, _, err := w.(Hijacker).Hijack()
4779 if err != nil {
4780 t.Error(err)
4781 return
4783 conn.Write([]byte("foo"))
4784 inHandler <- conn
4785 n, err := conn.Read([]byte{0})
4786 // The error should be io.EOF or "read tcp
4787 // 127.0.0.1:35827->127.0.0.1:40290: read: connection
4788 // reset by peer" depending on timing. Really we just
4789 // care that it returns at all. But if it returns with
4790 // data, that's weird.
4791 if n != 0 || err == nil {
4792 handlerResult <- fmt.Errorf("unexpected Read result: %v, %v", n, err)
4793 return
4795 handlerResult <- nil
4797 defer cst.close()
4799 // Set Timeout to something very long but non-zero to exercise
4800 // the codepaths that check for it. But rather than wait for it to fire
4801 // (which would make the test slow), we send on the req.Cancel channel instead,
4802 // which happens to exercise the same code paths.
4803 cst.c.Timeout = time.Minute // just to be non-zero, not to hit it.
4804 req, _ := NewRequest("GET", cst.ts.URL, nil)
4805 cancel := make(chan struct{})
4806 req.Cancel = cancel
4808 res, err := cst.c.Do(req)
4809 if err != nil {
4810 select {
4811 case <-inHandler:
4812 t.Fatalf("Get error: %v", err)
4813 default:
4814 // Failed before entering handler. Ignore result.
4815 t.Skip("skipping test on slow builder")
4819 close(cancel)
4820 got, err := ioutil.ReadAll(res.Body)
4821 if err == nil {
4822 t.Fatalf("unexpected success; read %q, nil", got)
4825 select {
4826 case c := <-inHandler:
4827 select {
4828 case err := <-handlerResult:
4829 if err != nil {
4830 t.Errorf("handler: %v", err)
4832 return
4833 case <-time.After(5 * time.Second):
4834 t.Error("Handler's conn.Read seems to be stuck in Read")
4835 c.Close() // close it to unblock Handler
4837 case <-time.After(5 * time.Second):
4838 t.Fatal("timeout")