github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/net/http2/transport_test.go (about)

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package http2
     6  
     7  import (
     8  	"bufio"
     9  	"bytes"
    10  	"crypto/tls"
    11  	"errors"
    12  	"flag"
    13  	"fmt"
    14  	"io"
    15  	"io/ioutil"
    16  	"log"
    17  	"math/rand"
    18  	"net"
    19  	"net/http"
    20  	"net/url"
    21  	"os"
    22  	"reflect"
    23  	"strconv"
    24  	"strings"
    25  	"sync"
    26  	"sync/atomic"
    27  	"testing"
    28  	"time"
    29  
    30  	"golang.org/x/net/http2/hpack"
    31  )
    32  
    33  var (
    34  	extNet        = flag.Bool("extnet", false, "do external network tests")
    35  	transportHost = flag.String("transporthost", "http2.golang.org", "hostname to use for TestTransport")
    36  	insecure      = flag.Bool("insecure", false, "insecure TLS dials") // TODO: dead code. remove?
    37  )
    38  
    39  var tlsConfigInsecure = &tls.Config{InsecureSkipVerify: true}
    40  
    41  func TestTransportExternal(t *testing.T) {
    42  	if !*extNet {
    43  		t.Skip("skipping external network test")
    44  	}
    45  	req, _ := http.NewRequest("GET", "https://"+*transportHost+"/", nil)
    46  	rt := &Transport{TLSClientConfig: tlsConfigInsecure}
    47  	res, err := rt.RoundTrip(req)
    48  	if err != nil {
    49  		t.Fatalf("%v", err)
    50  	}
    51  	res.Write(os.Stdout)
    52  }
    53  
    54  func TestTransport(t *testing.T) {
    55  	const body = "sup"
    56  	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
    57  		io.WriteString(w, body)
    58  	}, optOnlyServer)
    59  	defer st.Close()
    60  
    61  	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
    62  	defer tr.CloseIdleConnections()
    63  
    64  	req, err := http.NewRequest("GET", st.ts.URL, nil)
    65  	if err != nil {
    66  		t.Fatal(err)
    67  	}
    68  	res, err := tr.RoundTrip(req)
    69  	if err != nil {
    70  		t.Fatal(err)
    71  	}
    72  	defer res.Body.Close()
    73  
    74  	t.Logf("Got res: %+v", res)
    75  	if g, w := res.StatusCode, 200; g != w {
    76  		t.Errorf("StatusCode = %v; want %v", g, w)
    77  	}
    78  	if g, w := res.Status, "200 OK"; g != w {
    79  		t.Errorf("Status = %q; want %q", g, w)
    80  	}
    81  	wantHeader := http.Header{
    82  		"Content-Length": []string{"3"},
    83  		"Content-Type":   []string{"text/plain; charset=utf-8"},
    84  		"Date":           []string{"XXX"}, // see cleanDate
    85  	}
    86  	cleanDate(res)
    87  	if !reflect.DeepEqual(res.Header, wantHeader) {
    88  		t.Errorf("res Header = %v; want %v", res.Header, wantHeader)
    89  	}
    90  	if res.Request != req {
    91  		t.Errorf("Response.Request = %p; want %p", res.Request, req)
    92  	}
    93  	if res.TLS == nil {
    94  		t.Error("Response.TLS = nil; want non-nil")
    95  	}
    96  	slurp, err := ioutil.ReadAll(res.Body)
    97  	if err != nil {
    98  		t.Errorf("Body read: %v", err)
    99  	} else if string(slurp) != body {
   100  		t.Errorf("Body = %q; want %q", slurp, body)
   101  	}
   102  
   103  }
   104  
   105  func TestTransportReusesConns(t *testing.T) {
   106  	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
   107  		io.WriteString(w, r.RemoteAddr)
   108  	}, optOnlyServer)
   109  	defer st.Close()
   110  	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
   111  	defer tr.CloseIdleConnections()
   112  	get := func() string {
   113  		req, err := http.NewRequest("GET", st.ts.URL, nil)
   114  		if err != nil {
   115  			t.Fatal(err)
   116  		}
   117  		res, err := tr.RoundTrip(req)
   118  		if err != nil {
   119  			t.Fatal(err)
   120  		}
   121  		defer res.Body.Close()
   122  		slurp, err := ioutil.ReadAll(res.Body)
   123  		if err != nil {
   124  			t.Fatalf("Body read: %v", err)
   125  		}
   126  		addr := strings.TrimSpace(string(slurp))
   127  		if addr == "" {
   128  			t.Fatalf("didn't get an addr in response")
   129  		}
   130  		return addr
   131  	}
   132  	first := get()
   133  	second := get()
   134  	if first != second {
   135  		t.Errorf("first and second responses were on different connections: %q vs %q", first, second)
   136  	}
   137  }
   138  
   139  // Tests that the Transport only keeps one pending dial open per destination address.
   140  // https://golang.org/issue/13397
   141  func TestTransportGroupsPendingDials(t *testing.T) {
   142  	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
   143  		io.WriteString(w, r.RemoteAddr)
   144  	}, optOnlyServer)
   145  	defer st.Close()
   146  	tr := &Transport{
   147  		TLSClientConfig: tlsConfigInsecure,
   148  	}
   149  	defer tr.CloseIdleConnections()
   150  	var (
   151  		mu    sync.Mutex
   152  		dials = map[string]int{}
   153  	)
   154  	var wg sync.WaitGroup
   155  	for i := 0; i < 10; i++ {
   156  		wg.Add(1)
   157  		go func() {
   158  			defer wg.Done()
   159  			req, err := http.NewRequest("GET", st.ts.URL, nil)
   160  			if err != nil {
   161  				t.Error(err)
   162  				return
   163  			}
   164  			res, err := tr.RoundTrip(req)
   165  			if err != nil {
   166  				t.Error(err)
   167  				return
   168  			}
   169  			defer res.Body.Close()
   170  			slurp, err := ioutil.ReadAll(res.Body)
   171  			if err != nil {
   172  				t.Errorf("Body read: %v", err)
   173  			}
   174  			addr := strings.TrimSpace(string(slurp))
   175  			if addr == "" {
   176  				t.Errorf("didn't get an addr in response")
   177  			}
   178  			mu.Lock()
   179  			dials[addr]++
   180  			mu.Unlock()
   181  		}()
   182  	}
   183  	wg.Wait()
   184  	if len(dials) != 1 {
   185  		t.Errorf("saw %d dials; want 1: %v", len(dials), dials)
   186  	}
   187  	tr.CloseIdleConnections()
   188  	if err := retry(50, 10*time.Millisecond, func() error {
   189  		cp, ok := tr.connPool().(*clientConnPool)
   190  		if !ok {
   191  			return fmt.Errorf("Conn pool is %T; want *clientConnPool", tr.connPool())
   192  		}
   193  		cp.mu.Lock()
   194  		defer cp.mu.Unlock()
   195  		if len(cp.dialing) != 0 {
   196  			return fmt.Errorf("dialing map = %v; want empty", cp.dialing)
   197  		}
   198  		if len(cp.conns) != 0 {
   199  			return fmt.Errorf("conns = %v; want empty", cp.conns)
   200  		}
   201  		if len(cp.keys) != 0 {
   202  			return fmt.Errorf("keys = %v; want empty", cp.keys)
   203  		}
   204  		return nil
   205  	}); err != nil {
   206  		t.Errorf("State of pool after CloseIdleConnections: %v", err)
   207  	}
   208  }
   209  
   210  func retry(tries int, delay time.Duration, fn func() error) error {
   211  	var err error
   212  	for i := 0; i < tries; i++ {
   213  		err = fn()
   214  		if err == nil {
   215  			return nil
   216  		}
   217  		time.Sleep(delay)
   218  	}
   219  	return err
   220  }
   221  
   222  func TestTransportAbortClosesPipes(t *testing.T) {
   223  	shutdown := make(chan struct{})
   224  	st := newServerTester(t,
   225  		func(w http.ResponseWriter, r *http.Request) {
   226  			w.(http.Flusher).Flush()
   227  			<-shutdown
   228  		},
   229  		optOnlyServer,
   230  	)
   231  	defer st.Close()
   232  	defer close(shutdown) // we must shutdown before st.Close() to avoid hanging
   233  
   234  	done := make(chan struct{})
   235  	requestMade := make(chan struct{})
   236  	go func() {
   237  		defer close(done)
   238  		tr := &Transport{TLSClientConfig: tlsConfigInsecure}
   239  		req, err := http.NewRequest("GET", st.ts.URL, nil)
   240  		if err != nil {
   241  			t.Fatal(err)
   242  		}
   243  		res, err := tr.RoundTrip(req)
   244  		if err != nil {
   245  			t.Fatal(err)
   246  		}
   247  		defer res.Body.Close()
   248  		close(requestMade)
   249  		_, err = ioutil.ReadAll(res.Body)
   250  		if err == nil {
   251  			t.Error("expected error from res.Body.Read")
   252  		}
   253  	}()
   254  
   255  	<-requestMade
   256  	// Now force the serve loop to end, via closing the connection.
   257  	st.closeConn()
   258  	// deadlock? that's a bug.
   259  	select {
   260  	case <-done:
   261  	case <-time.After(3 * time.Second):
   262  		t.Fatal("timeout")
   263  	}
   264  }
   265  
   266  // TODO: merge this with TestTransportBody to make TestTransportRequest? This
   267  // could be a table-driven test with extra goodies.
   268  func TestTransportPath(t *testing.T) {
   269  	gotc := make(chan *url.URL, 1)
   270  	st := newServerTester(t,
   271  		func(w http.ResponseWriter, r *http.Request) {
   272  			gotc <- r.URL
   273  		},
   274  		optOnlyServer,
   275  	)
   276  	defer st.Close()
   277  
   278  	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
   279  	defer tr.CloseIdleConnections()
   280  	const (
   281  		path  = "/testpath"
   282  		query = "q=1"
   283  	)
   284  	surl := st.ts.URL + path + "?" + query
   285  	req, err := http.NewRequest("POST", surl, nil)
   286  	if err != nil {
   287  		t.Fatal(err)
   288  	}
   289  	c := &http.Client{Transport: tr}
   290  	res, err := c.Do(req)
   291  	if err != nil {
   292  		t.Fatal(err)
   293  	}
   294  	defer res.Body.Close()
   295  	got := <-gotc
   296  	if got.Path != path {
   297  		t.Errorf("Read Path = %q; want %q", got.Path, path)
   298  	}
   299  	if got.RawQuery != query {
   300  		t.Errorf("Read RawQuery = %q; want %q", got.RawQuery, query)
   301  	}
   302  }
   303  
   304  func randString(n int) string {
   305  	rnd := rand.New(rand.NewSource(int64(n)))
   306  	b := make([]byte, n)
   307  	for i := range b {
   308  		b[i] = byte(rnd.Intn(256))
   309  	}
   310  	return string(b)
   311  }
   312  
   313  var bodyTests = []struct {
   314  	body         string
   315  	noContentLen bool
   316  }{
   317  	{body: "some message"},
   318  	{body: "some message", noContentLen: true},
   319  	{body: ""},
   320  	{body: "", noContentLen: true},
   321  	{body: strings.Repeat("a", 1<<20), noContentLen: true},
   322  	{body: strings.Repeat("a", 1<<20)},
   323  	{body: randString(16<<10 - 1)},
   324  	{body: randString(16 << 10)},
   325  	{body: randString(16<<10 + 1)},
   326  	{body: randString(512<<10 - 1)},
   327  	{body: randString(512 << 10)},
   328  	{body: randString(512<<10 + 1)},
   329  	{body: randString(1<<20 - 1)},
   330  	{body: randString(1 << 20)},
   331  	{body: randString(1<<20 + 2)},
   332  }
   333  
   334  func TestTransportBody(t *testing.T) {
   335  	gotc := make(chan interface{}, 1)
   336  	st := newServerTester(t,
   337  		func(w http.ResponseWriter, r *http.Request) {
   338  			slurp, err := ioutil.ReadAll(r.Body)
   339  			if err != nil {
   340  				gotc <- err
   341  			} else {
   342  				gotc <- string(slurp)
   343  			}
   344  		},
   345  		optOnlyServer,
   346  	)
   347  	defer st.Close()
   348  
   349  	for i, tt := range bodyTests {
   350  		tr := &Transport{TLSClientConfig: tlsConfigInsecure}
   351  		defer tr.CloseIdleConnections()
   352  
   353  		var body io.Reader = strings.NewReader(tt.body)
   354  		if tt.noContentLen {
   355  			body = struct{ io.Reader }{body} // just a Reader, hiding concrete type and other methods
   356  		}
   357  		req, err := http.NewRequest("POST", st.ts.URL, body)
   358  		if err != nil {
   359  			t.Fatalf("#%d: %v", i, err)
   360  		}
   361  		c := &http.Client{Transport: tr}
   362  		res, err := c.Do(req)
   363  		if err != nil {
   364  			t.Fatalf("#%d: %v", i, err)
   365  		}
   366  		defer res.Body.Close()
   367  		got := <-gotc
   368  		if err, ok := got.(error); ok {
   369  			t.Fatalf("#%d: %v", i, err)
   370  		} else if got.(string) != tt.body {
   371  			got := got.(string)
   372  			t.Errorf("#%d: Read body mismatch.\n got: %q (len %d)\nwant: %q (len %d)", i, shortString(got), len(got), shortString(tt.body), len(tt.body))
   373  		}
   374  	}
   375  }
   376  
   377  func shortString(v string) string {
   378  	const maxLen = 100
   379  	if len(v) <= maxLen {
   380  		return v
   381  	}
   382  	return fmt.Sprintf("%v[...%d bytes omitted...]%v", v[:maxLen/2], len(v)-maxLen, v[len(v)-maxLen/2:])
   383  }
   384  
   385  func TestTransportDialTLS(t *testing.T) {
   386  	var mu sync.Mutex // guards following
   387  	var gotReq, didDial bool
   388  
   389  	ts := newServerTester(t,
   390  		func(w http.ResponseWriter, r *http.Request) {
   391  			mu.Lock()
   392  			gotReq = true
   393  			mu.Unlock()
   394  		},
   395  		optOnlyServer,
   396  	)
   397  	defer ts.Close()
   398  	tr := &Transport{
   399  		DialTLS: func(netw, addr string, cfg *tls.Config) (net.Conn, error) {
   400  			mu.Lock()
   401  			didDial = true
   402  			mu.Unlock()
   403  			cfg.InsecureSkipVerify = true
   404  			c, err := tls.Dial(netw, addr, cfg)
   405  			if err != nil {
   406  				return nil, err
   407  			}
   408  			return c, c.Handshake()
   409  		},
   410  	}
   411  	defer tr.CloseIdleConnections()
   412  	client := &http.Client{Transport: tr}
   413  	res, err := client.Get(ts.ts.URL)
   414  	if err != nil {
   415  		t.Fatal(err)
   416  	}
   417  	res.Body.Close()
   418  	mu.Lock()
   419  	if !gotReq {
   420  		t.Error("didn't get request")
   421  	}
   422  	if !didDial {
   423  		t.Error("didn't use dial hook")
   424  	}
   425  }
   426  
   427  func TestConfigureTransport(t *testing.T) {
   428  	t1 := &http.Transport{}
   429  	err := ConfigureTransport(t1)
   430  	if err == errTransportVersion {
   431  		t.Skip(err)
   432  	}
   433  	if err != nil {
   434  		t.Fatal(err)
   435  	}
   436  	if got := fmt.Sprintf("%#v", *t1); !strings.Contains(got, `"h2"`) {
   437  		// Laziness, to avoid buildtags.
   438  		t.Errorf("stringification of HTTP/1 transport didn't contain \"h2\": %v", got)
   439  	}
   440  	wantNextProtos := []string{"h2", "http/1.1"}
   441  	if t1.TLSClientConfig == nil {
   442  		t.Errorf("nil t1.TLSClientConfig")
   443  	} else if !reflect.DeepEqual(t1.TLSClientConfig.NextProtos, wantNextProtos) {
   444  		t.Errorf("TLSClientConfig.NextProtos = %q; want %q", t1.TLSClientConfig.NextProtos, wantNextProtos)
   445  	}
   446  	if err := ConfigureTransport(t1); err == nil {
   447  		t.Error("unexpected success on second call to ConfigureTransport")
   448  	}
   449  
   450  	// And does it work?
   451  	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
   452  		io.WriteString(w, r.Proto)
   453  	}, optOnlyServer)
   454  	defer st.Close()
   455  
   456  	t1.TLSClientConfig.InsecureSkipVerify = true
   457  	c := &http.Client{Transport: t1}
   458  	res, err := c.Get(st.ts.URL)
   459  	if err != nil {
   460  		t.Fatal(err)
   461  	}
   462  	slurp, err := ioutil.ReadAll(res.Body)
   463  	if err != nil {
   464  		t.Fatal(err)
   465  	}
   466  	if got, want := string(slurp), "HTTP/2.0"; got != want {
   467  		t.Errorf("body = %q; want %q", got, want)
   468  	}
   469  }
   470  
   471  type capitalizeReader struct {
   472  	r io.Reader
   473  }
   474  
   475  func (cr capitalizeReader) Read(p []byte) (n int, err error) {
   476  	n, err = cr.r.Read(p)
   477  	for i, b := range p[:n] {
   478  		if b >= 'a' && b <= 'z' {
   479  			p[i] = b - ('a' - 'A')
   480  		}
   481  	}
   482  	return
   483  }
   484  
   485  type flushWriter struct {
   486  	w io.Writer
   487  }
   488  
   489  func (fw flushWriter) Write(p []byte) (n int, err error) {
   490  	n, err = fw.w.Write(p)
   491  	if f, ok := fw.w.(http.Flusher); ok {
   492  		f.Flush()
   493  	}
   494  	return
   495  }
   496  
   497  type clientTester struct {
   498  	t      *testing.T
   499  	tr     *Transport
   500  	sc, cc net.Conn // server and client conn
   501  	fr     *Framer  // server's framer
   502  	client func() error
   503  	server func() error
   504  }
   505  
   506  func newClientTester(t *testing.T) *clientTester {
   507  	var dialOnce struct {
   508  		sync.Mutex
   509  		dialed bool
   510  	}
   511  	ct := &clientTester{
   512  		t: t,
   513  	}
   514  	ct.tr = &Transport{
   515  		TLSClientConfig: tlsConfigInsecure,
   516  		DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
   517  			dialOnce.Lock()
   518  			defer dialOnce.Unlock()
   519  			if dialOnce.dialed {
   520  				return nil, errors.New("only one dial allowed in test mode")
   521  			}
   522  			dialOnce.dialed = true
   523  			return ct.cc, nil
   524  		},
   525  	}
   526  
   527  	ln := newLocalListener(t)
   528  	cc, err := net.Dial("tcp", ln.Addr().String())
   529  	if err != nil {
   530  		t.Fatal(err)
   531  
   532  	}
   533  	sc, err := ln.Accept()
   534  	if err != nil {
   535  		t.Fatal(err)
   536  	}
   537  	ln.Close()
   538  	ct.cc = cc
   539  	ct.sc = sc
   540  	ct.fr = NewFramer(sc, sc)
   541  	return ct
   542  }
   543  
   544  func newLocalListener(t *testing.T) net.Listener {
   545  	ln, err := net.Listen("tcp4", "127.0.0.1:0")
   546  	if err == nil {
   547  		return ln
   548  	}
   549  	ln, err = net.Listen("tcp6", "[::1]:0")
   550  	if err != nil {
   551  		t.Fatal(err)
   552  	}
   553  	return ln
   554  }
   555  
   556  func (ct *clientTester) greet() {
   557  	buf := make([]byte, len(ClientPreface))
   558  	_, err := io.ReadFull(ct.sc, buf)
   559  	if err != nil {
   560  		ct.t.Fatalf("reading client preface: %v", err)
   561  	}
   562  	f, err := ct.fr.ReadFrame()
   563  	if err != nil {
   564  		ct.t.Fatalf("Reading client settings frame: %v", err)
   565  	}
   566  	if sf, ok := f.(*SettingsFrame); !ok {
   567  		ct.t.Fatalf("Wanted client settings frame; got %v", f)
   568  		_ = sf // stash it away?
   569  	}
   570  	if err := ct.fr.WriteSettings(); err != nil {
   571  		ct.t.Fatal(err)
   572  	}
   573  	if err := ct.fr.WriteSettingsAck(); err != nil {
   574  		ct.t.Fatal(err)
   575  	}
   576  }
   577  
   578  func (ct *clientTester) run() {
   579  	errc := make(chan error, 2)
   580  	ct.start("client", errc, ct.client)
   581  	ct.start("server", errc, ct.server)
   582  	for i := 0; i < 2; i++ {
   583  		if err := <-errc; err != nil {
   584  			ct.t.Error(err)
   585  			return
   586  		}
   587  	}
   588  }
   589  
   590  func (ct *clientTester) start(which string, errc chan<- error, fn func() error) {
   591  	go func() {
   592  		finished := false
   593  		var err error
   594  		defer func() {
   595  			if !finished {
   596  				err = fmt.Errorf("%s goroutine didn't finish.", which)
   597  			} else if err != nil {
   598  				err = fmt.Errorf("%s: %v", which, err)
   599  			}
   600  			errc <- err
   601  		}()
   602  		err = fn()
   603  		finished = true
   604  	}()
   605  }
   606  
   607  type countingReader struct {
   608  	n *int64
   609  }
   610  
   611  func (r countingReader) Read(p []byte) (n int, err error) {
   612  	for i := range p {
   613  		p[i] = byte(i)
   614  	}
   615  	atomic.AddInt64(r.n, int64(len(p)))
   616  	return len(p), err
   617  }
   618  
   619  func TestTransportReqBodyAfterResponse_200(t *testing.T) { testTransportReqBodyAfterResponse(t, 200) }
   620  func TestTransportReqBodyAfterResponse_403(t *testing.T) { testTransportReqBodyAfterResponse(t, 403) }
   621  
   622  func testTransportReqBodyAfterResponse(t *testing.T, status int) {
   623  	const bodySize = 10 << 20
   624  	ct := newClientTester(t)
   625  	ct.client = func() error {
   626  		var n int64 // atomic
   627  		req, err := http.NewRequest("PUT", "https://dummy.tld/", io.LimitReader(countingReader{&n}, bodySize))
   628  		if err != nil {
   629  			return err
   630  		}
   631  		res, err := ct.tr.RoundTrip(req)
   632  		if err != nil {
   633  			return fmt.Errorf("RoundTrip: %v", err)
   634  		}
   635  		defer res.Body.Close()
   636  		if res.StatusCode != status {
   637  			return fmt.Errorf("status code = %v; want %v", res.StatusCode, status)
   638  		}
   639  		slurp, err := ioutil.ReadAll(res.Body)
   640  		if err != nil {
   641  			return fmt.Errorf("Slurp: %v", err)
   642  		}
   643  		if len(slurp) > 0 {
   644  			return fmt.Errorf("unexpected body: %q", slurp)
   645  		}
   646  		if status == 200 {
   647  			if got := atomic.LoadInt64(&n); got != bodySize {
   648  				return fmt.Errorf("For 200 response, Transport wrote %d bytes; want %d", got, bodySize)
   649  			}
   650  		} else {
   651  			if got := atomic.LoadInt64(&n); got == 0 || got >= bodySize {
   652  				return fmt.Errorf("For %d response, Transport wrote %d bytes; want (0,%d) exclusive", status, got, bodySize)
   653  			}
   654  		}
   655  		return nil
   656  	}
   657  	ct.server = func() error {
   658  		ct.greet()
   659  		var buf bytes.Buffer
   660  		enc := hpack.NewEncoder(&buf)
   661  		var dataRecv int64
   662  		var closed bool
   663  		for {
   664  			f, err := ct.fr.ReadFrame()
   665  			if err != nil {
   666  				return err
   667  			}
   668  			//println(fmt.Sprintf("server got frame: %v", f))
   669  			switch f := f.(type) {
   670  			case *WindowUpdateFrame, *SettingsFrame:
   671  			case *HeadersFrame:
   672  				if !f.HeadersEnded() {
   673  					return fmt.Errorf("headers should have END_HEADERS be ended: %v", f)
   674  				}
   675  				if f.StreamEnded() {
   676  					return fmt.Errorf("headers contains END_STREAM unexpectedly: %v", f)
   677  				}
   678  				time.Sleep(50 * time.Millisecond) // let client send body
   679  				enc.WriteField(hpack.HeaderField{Name: ":status", Value: strconv.Itoa(status)})
   680  				ct.fr.WriteHeaders(HeadersFrameParam{
   681  					StreamID:      f.StreamID,
   682  					EndHeaders:    true,
   683  					EndStream:     false,
   684  					BlockFragment: buf.Bytes(),
   685  				})
   686  			case *DataFrame:
   687  				dataLen := len(f.Data())
   688  				dataRecv += int64(dataLen)
   689  				if dataLen > 0 {
   690  					if err := ct.fr.WriteWindowUpdate(0, uint32(dataLen)); err != nil {
   691  						return err
   692  					}
   693  					if err := ct.fr.WriteWindowUpdate(f.StreamID, uint32(dataLen)); err != nil {
   694  						return err
   695  					}
   696  				}
   697  				if !closed && ((status != 200 && dataRecv > 0) ||
   698  					(status == 200 && dataRecv == bodySize)) {
   699  					closed = true
   700  					if err := ct.fr.WriteData(f.StreamID, true, nil); err != nil {
   701  						return err
   702  					}
   703  					return nil
   704  				}
   705  			default:
   706  				return fmt.Errorf("Unexpected client frame %v", f)
   707  			}
   708  		}
   709  		return nil
   710  	}
   711  	ct.run()
   712  }
   713  
   714  // See golang.org/issue/13444
   715  func TestTransportFullDuplex(t *testing.T) {
   716  	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
   717  		w.WriteHeader(200) // redundant but for clarity
   718  		w.(http.Flusher).Flush()
   719  		io.Copy(flushWriter{w}, capitalizeReader{r.Body})
   720  		fmt.Fprintf(w, "bye.\n")
   721  	}, optOnlyServer)
   722  	defer st.Close()
   723  
   724  	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
   725  	defer tr.CloseIdleConnections()
   726  	c := &http.Client{Transport: tr}
   727  
   728  	pr, pw := io.Pipe()
   729  	req, err := http.NewRequest("PUT", st.ts.URL, ioutil.NopCloser(pr))
   730  	if err != nil {
   731  		log.Fatal(err)
   732  	}
   733  	res, err := c.Do(req)
   734  	if err != nil {
   735  		log.Fatal(err)
   736  	}
   737  	defer res.Body.Close()
   738  	if res.StatusCode != 200 {
   739  		t.Fatalf("StatusCode = %v; want %v", res.StatusCode, 200)
   740  	}
   741  	bs := bufio.NewScanner(res.Body)
   742  	want := func(v string) {
   743  		if !bs.Scan() {
   744  			t.Fatalf("wanted to read %q but Scan() = false, err = %v", v, bs.Err())
   745  		}
   746  	}
   747  	write := func(v string) {
   748  		_, err := io.WriteString(pw, v)
   749  		if err != nil {
   750  			t.Fatalf("pipe write: %v", err)
   751  		}
   752  	}
   753  	write("foo\n")
   754  	want("FOO")
   755  	write("bar\n")
   756  	want("BAR")
   757  	pw.Close()
   758  	want("bye.")
   759  	if err := bs.Err(); err != nil {
   760  		t.Fatal(err)
   761  	}
   762  }
   763  
   764  func TestTransportConnectRequest(t *testing.T) {
   765  	gotc := make(chan *http.Request, 1)
   766  	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
   767  		gotc <- r
   768  	}, optOnlyServer)
   769  	defer st.Close()
   770  
   771  	u, err := url.Parse(st.ts.URL)
   772  	if err != nil {
   773  		t.Fatal(err)
   774  	}
   775  
   776  	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
   777  	defer tr.CloseIdleConnections()
   778  	c := &http.Client{Transport: tr}
   779  
   780  	tests := []struct {
   781  		req  *http.Request
   782  		want string
   783  	}{
   784  		{
   785  			req: &http.Request{
   786  				Method: "CONNECT",
   787  				Header: http.Header{},
   788  				URL:    u,
   789  			},
   790  			want: u.Host,
   791  		},
   792  		{
   793  			req: &http.Request{
   794  				Method: "CONNECT",
   795  				Header: http.Header{},
   796  				URL:    u,
   797  				Host:   "example.com:123",
   798  			},
   799  			want: "example.com:123",
   800  		},
   801  	}
   802  
   803  	for i, tt := range tests {
   804  		res, err := c.Do(tt.req)
   805  		if err != nil {
   806  			t.Errorf("%d. RoundTrip = %v", i, err)
   807  			continue
   808  		}
   809  		res.Body.Close()
   810  		req := <-gotc
   811  		if req.Method != "CONNECT" {
   812  			t.Errorf("method = %q; want CONNECT", req.Method)
   813  		}
   814  		if req.Host != tt.want {
   815  			t.Errorf("Host = %q; want %q", req.Host, tt.want)
   816  		}
   817  		if req.URL.Host != tt.want {
   818  			t.Errorf("URL.Host = %q; want %q", req.URL.Host, tt.want)
   819  		}
   820  	}
   821  }