github.com/sean-/go@v0.0.0-20151219100004-97f854cd7bb6/src/net/http/clientserver_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  // Tests that use both the client & server, in both HTTP/1 and HTTP/2 mode.
     6  
     7  package http_test
     8  
     9  import (
    10  	"bytes"
    11  	"compress/gzip"
    12  	"crypto/tls"
    13  	"fmt"
    14  	"io"
    15  	"io/ioutil"
    16  	"log"
    17  	. "net/http"
    18  	"net/http/httptest"
    19  	"os"
    20  	"reflect"
    21  	"sort"
    22  	"strings"
    23  	"sync"
    24  	"testing"
    25  )
    26  
    27  type clientServerTest struct {
    28  	t  *testing.T
    29  	h2 bool
    30  	h  Handler
    31  	ts *httptest.Server
    32  	tr *Transport
    33  	c  *Client
    34  }
    35  
    36  func (t *clientServerTest) close() {
    37  	t.tr.CloseIdleConnections()
    38  	t.ts.Close()
    39  }
    40  
    41  const (
    42  	h1Mode = false
    43  	h2Mode = true
    44  )
    45  
    46  func newClientServerTest(t *testing.T, h2 bool, h Handler) *clientServerTest {
    47  	cst := &clientServerTest{
    48  		t:  t,
    49  		h2: h2,
    50  		h:  h,
    51  		tr: &Transport{},
    52  	}
    53  	cst.c = &Client{Transport: cst.tr}
    54  	if !h2 {
    55  		cst.ts = httptest.NewServer(h)
    56  		return cst
    57  	}
    58  	cst.ts = httptest.NewUnstartedServer(h)
    59  	ExportHttp2ConfigureServer(cst.ts.Config, nil)
    60  	cst.ts.TLS = cst.ts.Config.TLSConfig
    61  	cst.ts.StartTLS()
    62  
    63  	cst.tr.TLSClientConfig = &tls.Config{
    64  		InsecureSkipVerify: true,
    65  	}
    66  	if err := ExportHttp2ConfigureTransport(cst.tr); err != nil {
    67  		t.Fatal(err)
    68  	}
    69  	return cst
    70  }
    71  
    72  // Testing the newClientServerTest helper itself.
    73  func TestNewClientServerTest(t *testing.T) {
    74  	var got struct {
    75  		sync.Mutex
    76  		log []string
    77  	}
    78  	h := HandlerFunc(func(w ResponseWriter, r *Request) {
    79  		got.Lock()
    80  		defer got.Unlock()
    81  		got.log = append(got.log, r.Proto)
    82  	})
    83  	for _, v := range [2]bool{false, true} {
    84  		cst := newClientServerTest(t, v, h)
    85  		if _, err := cst.c.Head(cst.ts.URL); err != nil {
    86  			t.Fatal(err)
    87  		}
    88  		cst.close()
    89  	}
    90  	got.Lock() // no need to unlock
    91  	if want := []string{"HTTP/1.1", "HTTP/2.0"}; !reflect.DeepEqual(got.log, want) {
    92  		t.Errorf("got %q; want %q", got.log, want)
    93  	}
    94  }
    95  
    96  func TestChunkedResponseHeaders_h1(t *testing.T) { testChunkedResponseHeaders(t, h1Mode) }
    97  func TestChunkedResponseHeaders_h2(t *testing.T) { testChunkedResponseHeaders(t, h2Mode) }
    98  
    99  func testChunkedResponseHeaders(t *testing.T, h2 bool) {
   100  	defer afterTest(t)
   101  	log.SetOutput(ioutil.Discard) // is noisy otherwise
   102  	defer log.SetOutput(os.Stderr)
   103  	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
   104  		w.Header().Set("Content-Length", "intentional gibberish") // we check that this is deleted
   105  		w.(Flusher).Flush()
   106  		fmt.Fprintf(w, "I am a chunked response.")
   107  	}))
   108  	defer cst.close()
   109  
   110  	res, err := cst.c.Get(cst.ts.URL)
   111  	if err != nil {
   112  		t.Fatalf("Get error: %v", err)
   113  	}
   114  	defer res.Body.Close()
   115  	if g, e := res.ContentLength, int64(-1); g != e {
   116  		t.Errorf("expected ContentLength of %d; got %d", e, g)
   117  	}
   118  	wantTE := []string{"chunked"}
   119  	if h2 {
   120  		wantTE = nil
   121  	}
   122  	if !reflect.DeepEqual(res.TransferEncoding, wantTE) {
   123  		t.Errorf("TransferEncoding = %v; want %v", res.TransferEncoding, wantTE)
   124  	}
   125  	if got, haveCL := res.Header["Content-Length"]; haveCL {
   126  		t.Errorf("Unexpected Content-Length: %q", got)
   127  	}
   128  }
   129  
   130  type reqFunc func(c *Client, url string) (*Response, error)
   131  
   132  // h12Compare is a test that compares HTTP/1 and HTTP/2 behavior
   133  // against each other.
   134  type h12Compare struct {
   135  	Handler       func(ResponseWriter, *Request)    // required
   136  	ReqFunc       reqFunc                           // optional
   137  	CheckResponse func(proto string, res *Response) // optional
   138  }
   139  
   140  func (tt h12Compare) reqFunc() reqFunc {
   141  	if tt.ReqFunc == nil {
   142  		return (*Client).Get
   143  	}
   144  	return tt.ReqFunc
   145  }
   146  
   147  func (tt h12Compare) run(t *testing.T) {
   148  	cst1 := newClientServerTest(t, false, HandlerFunc(tt.Handler))
   149  	defer cst1.close()
   150  	cst2 := newClientServerTest(t, true, HandlerFunc(tt.Handler))
   151  	defer cst2.close()
   152  
   153  	res1, err := tt.reqFunc()(cst1.c, cst1.ts.URL)
   154  	if err != nil {
   155  		t.Errorf("HTTP/1 request: %v", err)
   156  		return
   157  	}
   158  	res2, err := tt.reqFunc()(cst2.c, cst2.ts.URL)
   159  	if err != nil {
   160  		t.Errorf("HTTP/2 request: %v", err)
   161  		return
   162  	}
   163  	tt.normalizeRes(t, res1, "HTTP/1.1")
   164  	tt.normalizeRes(t, res2, "HTTP/2.0")
   165  	res1body, res2body := res1.Body, res2.Body
   166  
   167  	eres1 := mostlyCopy(res1)
   168  	eres2 := mostlyCopy(res2)
   169  	if !reflect.DeepEqual(eres1, eres2) {
   170  		t.Errorf("Response headers to handler differed:\nhttp/1 (%v):\n\t%#v\nhttp/2 (%v):\n\t%#v",
   171  			cst1.ts.URL, eres1, cst2.ts.URL, eres2)
   172  	}
   173  	if !reflect.DeepEqual(res1body, res2body) {
   174  		t.Errorf("Response bodies to handler differed.\nhttp1: %v\nhttp2: %v\n", res1body, res2body)
   175  	}
   176  	if fn := tt.CheckResponse; fn != nil {
   177  		res1.Body, res2.Body = res1body, res2body
   178  		fn("HTTP/1.1", res1)
   179  		fn("HTTP/2.0", res2)
   180  	}
   181  }
   182  
   183  func mostlyCopy(r *Response) *Response {
   184  	c := *r
   185  	c.Body = nil
   186  	c.TransferEncoding = nil
   187  	c.TLS = nil
   188  	c.Request = nil
   189  	return &c
   190  }
   191  
   192  type slurpResult struct {
   193  	io.ReadCloser
   194  	body []byte
   195  	err  error
   196  }
   197  
   198  func (sr slurpResult) String() string { return fmt.Sprintf("body %q; err %v", sr.body, sr.err) }
   199  
   200  func (tt h12Compare) normalizeRes(t *testing.T, res *Response, wantProto string) {
   201  	if res.Proto == wantProto {
   202  		res.Proto, res.ProtoMajor, res.ProtoMinor = "", 0, 0
   203  	} else {
   204  		t.Errorf("got %q response; want %q", res.Proto, wantProto)
   205  	}
   206  	slurp, err := ioutil.ReadAll(res.Body)
   207  	res.Body.Close()
   208  	res.Body = slurpResult{
   209  		ReadCloser: ioutil.NopCloser(bytes.NewReader(slurp)),
   210  		body:       slurp,
   211  		err:        err,
   212  	}
   213  	for i, v := range res.Header["Date"] {
   214  		res.Header["Date"][i] = strings.Repeat("x", len(v))
   215  	}
   216  	if res.Request == nil {
   217  		t.Errorf("for %s, no request", wantProto)
   218  	}
   219  	if (res.TLS != nil) != (wantProto == "HTTP/2.0") {
   220  		t.Errorf("TLS set = %v; want %v", res.TLS != nil, res.TLS == nil)
   221  	}
   222  }
   223  
   224  // Issue 13532
   225  func TestH12_HeadContentLengthNoBody(t *testing.T) {
   226  	h12Compare{
   227  		ReqFunc: (*Client).Head,
   228  		Handler: func(w ResponseWriter, r *Request) {
   229  		},
   230  	}.run(t)
   231  }
   232  
   233  func TestH12_HeadContentLengthSmallBody(t *testing.T) {
   234  	h12Compare{
   235  		ReqFunc: (*Client).Head,
   236  		Handler: func(w ResponseWriter, r *Request) {
   237  			io.WriteString(w, "small")
   238  		},
   239  	}.run(t)
   240  }
   241  
   242  func TestH12_HeadContentLengthLargeBody(t *testing.T) {
   243  	h12Compare{
   244  		ReqFunc: (*Client).Head,
   245  		Handler: func(w ResponseWriter, r *Request) {
   246  			chunk := strings.Repeat("x", 512<<10)
   247  			for i := 0; i < 10; i++ {
   248  				io.WriteString(w, chunk)
   249  			}
   250  		},
   251  	}.run(t)
   252  }
   253  
   254  func TestH12_200NoBody(t *testing.T) {
   255  	h12Compare{Handler: func(w ResponseWriter, r *Request) {}}.run(t)
   256  }
   257  
   258  func TestH2_204NoBody(t *testing.T) { testH12_noBody(t, 204) }
   259  func TestH2_304NoBody(t *testing.T) { testH12_noBody(t, 304) }
   260  func TestH2_404NoBody(t *testing.T) { testH12_noBody(t, 404) }
   261  
   262  func testH12_noBody(t *testing.T, status int) {
   263  	h12Compare{Handler: func(w ResponseWriter, r *Request) {
   264  		w.WriteHeader(status)
   265  	}}.run(t)
   266  }
   267  
   268  func TestH12_SmallBody(t *testing.T) {
   269  	h12Compare{Handler: func(w ResponseWriter, r *Request) {
   270  		io.WriteString(w, "small body")
   271  	}}.run(t)
   272  }
   273  
   274  func TestH12_ExplicitContentLength(t *testing.T) {
   275  	h12Compare{Handler: func(w ResponseWriter, r *Request) {
   276  		w.Header().Set("Content-Length", "3")
   277  		io.WriteString(w, "foo")
   278  	}}.run(t)
   279  }
   280  
   281  func TestH12_FlushBeforeBody(t *testing.T) {
   282  	h12Compare{Handler: func(w ResponseWriter, r *Request) {
   283  		w.(Flusher).Flush()
   284  		io.WriteString(w, "foo")
   285  	}}.run(t)
   286  }
   287  
   288  func TestH12_FlushMidBody(t *testing.T) {
   289  	h12Compare{Handler: func(w ResponseWriter, r *Request) {
   290  		io.WriteString(w, "foo")
   291  		w.(Flusher).Flush()
   292  		io.WriteString(w, "bar")
   293  	}}.run(t)
   294  }
   295  
   296  func TestH12_Head_ExplicitLen(t *testing.T) {
   297  	h12Compare{
   298  		ReqFunc: (*Client).Head,
   299  		Handler: func(w ResponseWriter, r *Request) {
   300  			if r.Method != "HEAD" {
   301  				t.Errorf("unexpected method %q", r.Method)
   302  			}
   303  			w.Header().Set("Content-Length", "1235")
   304  		},
   305  	}.run(t)
   306  }
   307  
   308  func TestH12_Head_ImplicitLen(t *testing.T) {
   309  	h12Compare{
   310  		ReqFunc: (*Client).Head,
   311  		Handler: func(w ResponseWriter, r *Request) {
   312  			if r.Method != "HEAD" {
   313  				t.Errorf("unexpected method %q", r.Method)
   314  			}
   315  			io.WriteString(w, "foo")
   316  		},
   317  	}.run(t)
   318  }
   319  
   320  func TestH12_HandlerWritesTooLittle(t *testing.T) {
   321  	h12Compare{
   322  		Handler: func(w ResponseWriter, r *Request) {
   323  			w.Header().Set("Content-Length", "3")
   324  			io.WriteString(w, "12") // one byte short
   325  		},
   326  		CheckResponse: func(proto string, res *Response) {
   327  			sr, ok := res.Body.(slurpResult)
   328  			if !ok {
   329  				t.Errorf("%s body is %T; want slurpResult", proto, res.Body)
   330  				return
   331  			}
   332  			if sr.err != io.ErrUnexpectedEOF {
   333  				t.Errorf("%s read error = %v; want io.ErrUnexpectedEOF", proto, sr.err)
   334  			}
   335  			if string(sr.body) != "12" {
   336  				t.Errorf("%s body = %q; want %q", proto, sr.body, "12")
   337  			}
   338  		},
   339  	}.run(t)
   340  }
   341  
   342  // Tests that the HTTP/1 and HTTP/2 servers prevent handlers from
   343  // writing more than they declared.  This test does not test whether
   344  // the transport deals with too much data, though, since the server
   345  // doesn't make it possible to send bogus data. For those tests, see
   346  // transport_test.go (for HTTP/1) or x/net/http2/transport_test.go
   347  // (for HTTP/2).
   348  func TestH12_HandlerWritesTooMuch(t *testing.T) {
   349  	h12Compare{
   350  		Handler: func(w ResponseWriter, r *Request) {
   351  			w.Header().Set("Content-Length", "3")
   352  			w.(Flusher).Flush()
   353  			io.WriteString(w, "123")
   354  			w.(Flusher).Flush()
   355  			n, err := io.WriteString(w, "x") // too many
   356  			if n > 0 || err == nil {
   357  				t.Errorf("for proto %q, final write = %v, %v; want 0, some error", r.Proto, n, err)
   358  			}
   359  		},
   360  	}.run(t)
   361  }
   362  
   363  // Verify that both our HTTP/1 and HTTP/2 request and auto-decompress gzip.
   364  // Some hosts send gzip even if you don't ask for it; see golang.org/issue/13298
   365  func TestH12_AutoGzip(t *testing.T) {
   366  	h12Compare{
   367  		Handler: func(w ResponseWriter, r *Request) {
   368  			if ae := r.Header.Get("Accept-Encoding"); ae != "gzip" {
   369  				t.Errorf("%s Accept-Encoding = %q; want gzip", r.Proto, ae)
   370  			}
   371  			w.Header().Set("Content-Encoding", "gzip")
   372  			gz := gzip.NewWriter(w)
   373  			io.WriteString(gz, "I am some gzipped content. Go go go go go go go go go go go go should compress well.")
   374  			gz.Close()
   375  		},
   376  	}.run(t)
   377  }
   378  
   379  // Test304Responses verifies that 304s don't declare that they're
   380  // chunking in their response headers and aren't allowed to produce
   381  // output.
   382  func Test304Responses_h1(t *testing.T) { test304Responses(t, h1Mode) }
   383  func Test304Responses_h2(t *testing.T) { test304Responses(t, h2Mode) }
   384  
   385  func test304Responses(t *testing.T, h2 bool) {
   386  	defer afterTest(t)
   387  	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
   388  		w.WriteHeader(StatusNotModified)
   389  		_, err := w.Write([]byte("illegal body"))
   390  		if err != ErrBodyNotAllowed {
   391  			t.Errorf("on Write, expected ErrBodyNotAllowed, got %v", err)
   392  		}
   393  	}))
   394  	defer cst.close()
   395  	res, err := cst.c.Get(cst.ts.URL)
   396  	if err != nil {
   397  		t.Fatal(err)
   398  	}
   399  	if len(res.TransferEncoding) > 0 {
   400  		t.Errorf("expected no TransferEncoding; got %v", res.TransferEncoding)
   401  	}
   402  	body, err := ioutil.ReadAll(res.Body)
   403  	if err != nil {
   404  		t.Error(err)
   405  	}
   406  	if len(body) > 0 {
   407  		t.Errorf("got unexpected body %q", string(body))
   408  	}
   409  }
   410  
   411  func TestH12_ServerEmptyContentLength(t *testing.T) {
   412  	h12Compare{
   413  		Handler: func(w ResponseWriter, r *Request) {
   414  			w.Header()["Content-Type"] = []string{""}
   415  			io.WriteString(w, "<html><body>hi</body></html>")
   416  		},
   417  	}.run(t)
   418  }
   419  
   420  // Tests that closing the Request.Cancel channel also while still
   421  // reading the response body. Issue 13159.
   422  func TestCancelRequestMidBody_h1(t *testing.T) { testCancelRequestMidBody(t, h1Mode) }
   423  func TestCancelRequestMidBody_h2(t *testing.T) { testCancelRequestMidBody(t, h2Mode) }
   424  func testCancelRequestMidBody(t *testing.T, h2 bool) {
   425  	defer afterTest(t)
   426  	unblock := make(chan bool)
   427  	didFlush := make(chan bool, 1)
   428  	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
   429  		io.WriteString(w, "Hello")
   430  		w.(Flusher).Flush()
   431  		didFlush <- true
   432  		<-unblock
   433  		io.WriteString(w, ", world.")
   434  	}))
   435  	defer cst.close()
   436  	defer close(unblock)
   437  
   438  	req, _ := NewRequest("GET", cst.ts.URL, nil)
   439  	cancel := make(chan struct{})
   440  	req.Cancel = cancel
   441  
   442  	res, err := cst.c.Do(req)
   443  	if err != nil {
   444  		t.Fatal(err)
   445  	}
   446  	defer res.Body.Close()
   447  	<-didFlush
   448  
   449  	// Read a bit before we cancel. (Issue 13626)
   450  	// We should have "Hello" at least sitting there.
   451  	firstRead := make([]byte, 10)
   452  	n, err := res.Body.Read(firstRead)
   453  	if err != nil {
   454  		t.Fatal(err)
   455  	}
   456  	firstRead = firstRead[:n]
   457  
   458  	close(cancel)
   459  
   460  	rest, err := ioutil.ReadAll(res.Body)
   461  	all := string(firstRead) + string(rest)
   462  	if all != "Hello" {
   463  		t.Errorf("Read %q (%q + %q); want Hello", all, firstRead, rest)
   464  	}
   465  	if !reflect.DeepEqual(err, ExportErrRequestCanceled) {
   466  		t.Errorf("ReadAll error = %v; want %v", err, ExportErrRequestCanceled)
   467  	}
   468  }
   469  
   470  // Tests that clients can send trailers to a server and that the server can read them.
   471  func TestTrailersClientToServer_h1(t *testing.T) { testTrailersClientToServer(t, h1Mode) }
   472  func TestTrailersClientToServer_h2(t *testing.T) { testTrailersClientToServer(t, h2Mode) }
   473  
   474  func testTrailersClientToServer(t *testing.T, h2 bool) {
   475  	defer afterTest(t)
   476  	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
   477  		var decl []string
   478  		for k := range r.Trailer {
   479  			decl = append(decl, k)
   480  		}
   481  		sort.Strings(decl)
   482  
   483  		slurp, err := ioutil.ReadAll(r.Body)
   484  		if err != nil {
   485  			t.Errorf("Server reading request body: %v", err)
   486  		}
   487  		if string(slurp) != "foo" {
   488  			t.Errorf("Server read request body %q; want foo", slurp)
   489  		}
   490  		if r.Trailer == nil {
   491  			io.WriteString(w, "nil Trailer")
   492  		} else {
   493  			fmt.Fprintf(w, "decl: %v, vals: %s, %s",
   494  				decl,
   495  				r.Trailer.Get("Client-Trailer-A"),
   496  				r.Trailer.Get("Client-Trailer-B"))
   497  		}
   498  	}))
   499  	defer cst.close()
   500  
   501  	var req *Request
   502  	req, _ = NewRequest("POST", cst.ts.URL, io.MultiReader(
   503  		eofReaderFunc(func() {
   504  			req.Trailer["Client-Trailer-A"] = []string{"valuea"}
   505  		}),
   506  		strings.NewReader("foo"),
   507  		eofReaderFunc(func() {
   508  			req.Trailer["Client-Trailer-B"] = []string{"valueb"}
   509  		}),
   510  	))
   511  	req.Trailer = Header{
   512  		"Client-Trailer-A": nil, //  to be set later
   513  		"Client-Trailer-B": nil, //  to be set later
   514  	}
   515  	req.ContentLength = -1
   516  	res, err := cst.c.Do(req)
   517  	if err != nil {
   518  		t.Fatal(err)
   519  	}
   520  	if err := wantBody(res, err, "decl: [Client-Trailer-A Client-Trailer-B], vals: valuea, valueb"); err != nil {
   521  		t.Error(err)
   522  	}
   523  }
   524  
   525  // Tests that servers send trailers to a client and that the client can read them.
   526  func TestTrailersServerToClient_h1(t *testing.T)       { testTrailersServerToClient(t, h1Mode, false) }
   527  func TestTrailersServerToClient_h2(t *testing.T)       { testTrailersServerToClient(t, h2Mode, false) }
   528  func TestTrailersServerToClient_Flush_h1(t *testing.T) { testTrailersServerToClient(t, h1Mode, true) }
   529  func TestTrailersServerToClient_Flush_h2(t *testing.T) { testTrailersServerToClient(t, h2Mode, true) }
   530  
   531  func testTrailersServerToClient(t *testing.T, h2, flush bool) {
   532  	defer afterTest(t)
   533  	const body = "Some body"
   534  	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
   535  		w.Header().Set("Trailer", "Server-Trailer-A, Server-Trailer-B")
   536  		w.Header().Add("Trailer", "Server-Trailer-C")
   537  
   538  		io.WriteString(w, body)
   539  		if flush {
   540  			w.(Flusher).Flush()
   541  		}
   542  
   543  		// How handlers set Trailers: declare it ahead of time
   544  		// with the Trailer header, and then mutate the
   545  		// Header() of those values later, after the response
   546  		// has been written (we wrote to w above).
   547  		w.Header().Set("Server-Trailer-A", "valuea")
   548  		w.Header().Set("Server-Trailer-C", "valuec") // skipping B
   549  		w.Header().Set("Server-Trailer-NotDeclared", "should be omitted")
   550  	}))
   551  	defer cst.close()
   552  
   553  	res, err := cst.c.Get(cst.ts.URL)
   554  	if err != nil {
   555  		t.Fatal(err)
   556  	}
   557  
   558  	wantHeader := Header{
   559  		"Content-Type": {"text/plain; charset=utf-8"},
   560  	}
   561  	wantLen := -1
   562  	if h2 && !flush {
   563  		// In HTTP/1.1, any use of trailers forces HTTP/1.1
   564  		// chunking and a flush at the first write. That's
   565  		// unnecessary with HTTP/2's framing, so the server
   566  		// is able to calculate the length while still sending
   567  		// trailers afterwards.
   568  		wantLen = len(body)
   569  		wantHeader["Content-Length"] = []string{fmt.Sprint(wantLen)}
   570  	}
   571  	if res.ContentLength != int64(wantLen) {
   572  		t.Errorf("ContentLength = %v; want %v", res.ContentLength, wantLen)
   573  	}
   574  
   575  	delete(res.Header, "Date") // irrelevant for test
   576  	if !reflect.DeepEqual(res.Header, wantHeader) {
   577  		t.Errorf("Header = %v; want %v", res.Header, wantHeader)
   578  	}
   579  
   580  	if got, want := res.Trailer, (Header{
   581  		"Server-Trailer-A": nil,
   582  		"Server-Trailer-B": nil,
   583  		"Server-Trailer-C": nil,
   584  	}); !reflect.DeepEqual(got, want) {
   585  		t.Errorf("Trailer before body read = %v; want %v", got, want)
   586  	}
   587  
   588  	if err := wantBody(res, nil, body); err != nil {
   589  		t.Fatal(err)
   590  	}
   591  
   592  	if got, want := res.Trailer, (Header{
   593  		"Server-Trailer-A": {"valuea"},
   594  		"Server-Trailer-B": nil,
   595  		"Server-Trailer-C": {"valuec"},
   596  	}); !reflect.DeepEqual(got, want) {
   597  		t.Errorf("Trailer after body read = %v; want %v", got, want)
   598  	}
   599  }
   600  
   601  // Don't allow a Body.Read after Body.Close. Issue 13648.
   602  func TestResponseBodyReadAfterClose_h1(t *testing.T) { testResponseBodyReadAfterClose(t, h1Mode) }
   603  func TestResponseBodyReadAfterClose_h2(t *testing.T) { testResponseBodyReadAfterClose(t, h2Mode) }
   604  
   605  func testResponseBodyReadAfterClose(t *testing.T, h2 bool) {
   606  	defer afterTest(t)
   607  	const body = "Some body"
   608  	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
   609  		io.WriteString(w, body)
   610  	}))
   611  	defer cst.close()
   612  	res, err := cst.c.Get(cst.ts.URL)
   613  	if err != nil {
   614  		t.Fatal(err)
   615  	}
   616  	res.Body.Close()
   617  	data, err := ioutil.ReadAll(res.Body)
   618  	if len(data) != 0 || err == nil {
   619  		t.Fatalf("ReadAll returned %q, %v; want error", data, err)
   620  	}
   621  }
   622  
   623  func TestConcurrentReadWriteReqBody_h1(t *testing.T) { testConcurrentReadWriteReqBody(t, h1Mode) }
   624  func TestConcurrentReadWriteReqBody_h2(t *testing.T) {
   625  	t.Skip("known failing; golang.org/issue/13659")
   626  	testConcurrentReadWriteReqBody(t, h2Mode)
   627  }
   628  func testConcurrentReadWriteReqBody(t *testing.T, h2 bool) {
   629  	defer afterTest(t)
   630  	const reqBody = "some request body"
   631  	const resBody = "some response body"
   632  	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
   633  		var wg sync.WaitGroup
   634  		wg.Add(2)
   635  		didRead := make(chan bool, 1)
   636  		// Read in one goroutine.
   637  		go func() {
   638  			defer wg.Done()
   639  			data, err := ioutil.ReadAll(r.Body)
   640  			if string(data) != reqBody {
   641  				t.Errorf("Handler read %q; want %q", data, reqBody)
   642  			}
   643  			if err != nil {
   644  				t.Errorf("Handler Read: %v", err)
   645  			}
   646  			didRead <- true
   647  		}()
   648  		// Write in another goroutine.
   649  		go func() {
   650  			defer wg.Done()
   651  			if !h2 {
   652  				// our HTTP/1 implementation intentionally
   653  				// doesn't permit writes during read (mostly
   654  				// due to it being undefined); if that is ever
   655  				// relaxed, fix this.
   656  				<-didRead
   657  			}
   658  			io.WriteString(w, resBody)
   659  		}()
   660  		wg.Wait()
   661  	}))
   662  	defer cst.close()
   663  	req, _ := NewRequest("POST", cst.ts.URL, strings.NewReader(reqBody))
   664  	req.Header.Add("Expect", "100-continue") // just to complicate things
   665  	res, err := cst.c.Do(req)
   666  	if err != nil {
   667  		t.Fatal(err)
   668  	}
   669  	data, err := ioutil.ReadAll(res.Body)
   670  	defer res.Body.Close()
   671  	if err != nil {
   672  		t.Fatal(err)
   673  	}
   674  	if string(data) != resBody {
   675  		t.Errorf("read %q; want %q", data, resBody)
   676  	}
   677  }