github.com/panjjo/go@v0.0.0-20161104043856-d62b31386338/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" 18 . "net/http" 19 "net/http/httptest" 20 "net/http/httputil" 21 "net/url" 22 "os" 23 "reflect" 24 "runtime" 25 "sort" 26 "strings" 27 "sync" 28 "sync/atomic" 29 "testing" 30 "time" 31 ) 32 33 type clientServerTest struct { 34 t *testing.T 35 h2 bool 36 h Handler 37 ts *httptest.Server 38 tr *Transport 39 c *Client 40 } 41 42 func (t *clientServerTest) close() { 43 t.tr.CloseIdleConnections() 44 t.ts.Close() 45 } 46 47 func (t *clientServerTest) scheme() string { 48 if t.h2 { 49 return "https" 50 } 51 return "http" 52 } 53 54 const ( 55 h1Mode = false 56 h2Mode = true 57 ) 58 59 func newClientServerTest(t *testing.T, h2 bool, h Handler, opts ...interface{}) *clientServerTest { 60 cst := &clientServerTest{ 61 t: t, 62 h2: h2, 63 h: h, 64 tr: &Transport{}, 65 } 66 cst.c = &Client{Transport: cst.tr} 67 68 for _, opt := range opts { 69 switch opt := opt.(type) { 70 case func(*Transport): 71 opt(cst.tr) 72 default: 73 t.Fatalf("unhandled option type %T", opt) 74 } 75 } 76 77 if !h2 { 78 cst.ts = httptest.NewServer(h) 79 return cst 80 } 81 cst.ts = httptest.NewUnstartedServer(h) 82 ExportHttp2ConfigureServer(cst.ts.Config, nil) 83 cst.ts.TLS = cst.ts.Config.TLSConfig 84 cst.ts.StartTLS() 85 86 cst.tr.TLSClientConfig = &tls.Config{ 87 InsecureSkipVerify: true, 88 } 89 if err := ExportHttp2ConfigureTransport(cst.tr); err != nil { 90 t.Fatal(err) 91 } 92 return cst 93 } 94 95 // Testing the newClientServerTest helper itself. 96 func TestNewClientServerTest(t *testing.T) { 97 var got struct { 98 sync.Mutex 99 log []string 100 } 101 h := HandlerFunc(func(w ResponseWriter, r *Request) { 102 got.Lock() 103 defer got.Unlock() 104 got.log = append(got.log, r.Proto) 105 }) 106 for _, v := range [2]bool{false, true} { 107 cst := newClientServerTest(t, v, h) 108 if _, err := cst.c.Head(cst.ts.URL); err != nil { 109 t.Fatal(err) 110 } 111 cst.close() 112 } 113 got.Lock() // no need to unlock 114 if want := []string{"HTTP/1.1", "HTTP/2.0"}; !reflect.DeepEqual(got.log, want) { 115 t.Errorf("got %q; want %q", got.log, want) 116 } 117 } 118 119 func TestChunkedResponseHeaders_h1(t *testing.T) { testChunkedResponseHeaders(t, h1Mode) } 120 func TestChunkedResponseHeaders_h2(t *testing.T) { testChunkedResponseHeaders(t, h2Mode) } 121 122 func testChunkedResponseHeaders(t *testing.T, h2 bool) { 123 defer afterTest(t) 124 log.SetOutput(ioutil.Discard) // is noisy otherwise 125 defer log.SetOutput(os.Stderr) 126 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 127 w.Header().Set("Content-Length", "intentional gibberish") // we check that this is deleted 128 w.(Flusher).Flush() 129 fmt.Fprintf(w, "I am a chunked response.") 130 })) 131 defer cst.close() 132 133 res, err := cst.c.Get(cst.ts.URL) 134 if err != nil { 135 t.Fatalf("Get error: %v", err) 136 } 137 defer res.Body.Close() 138 if g, e := res.ContentLength, int64(-1); g != e { 139 t.Errorf("expected ContentLength of %d; got %d", e, g) 140 } 141 wantTE := []string{"chunked"} 142 if h2 { 143 wantTE = nil 144 } 145 if !reflect.DeepEqual(res.TransferEncoding, wantTE) { 146 t.Errorf("TransferEncoding = %v; want %v", res.TransferEncoding, wantTE) 147 } 148 if got, haveCL := res.Header["Content-Length"]; haveCL { 149 t.Errorf("Unexpected Content-Length: %q", got) 150 } 151 } 152 153 type reqFunc func(c *Client, url string) (*Response, error) 154 155 // h12Compare is a test that compares HTTP/1 and HTTP/2 behavior 156 // against each other. 157 type h12Compare struct { 158 Handler func(ResponseWriter, *Request) // required 159 ReqFunc reqFunc // optional 160 CheckResponse func(proto string, res *Response) // optional 161 EarlyCheckResponse func(proto string, res *Response) // optional; pre-normalize 162 Opts []interface{} 163 } 164 165 func (tt h12Compare) reqFunc() reqFunc { 166 if tt.ReqFunc == nil { 167 return (*Client).Get 168 } 169 return tt.ReqFunc 170 } 171 172 func (tt h12Compare) run(t *testing.T) { 173 setParallel(t) 174 cst1 := newClientServerTest(t, false, HandlerFunc(tt.Handler), tt.Opts...) 175 defer cst1.close() 176 cst2 := newClientServerTest(t, true, HandlerFunc(tt.Handler), tt.Opts...) 177 defer cst2.close() 178 179 res1, err := tt.reqFunc()(cst1.c, cst1.ts.URL) 180 if err != nil { 181 t.Errorf("HTTP/1 request: %v", err) 182 return 183 } 184 res2, err := tt.reqFunc()(cst2.c, cst2.ts.URL) 185 if err != nil { 186 t.Errorf("HTTP/2 request: %v", err) 187 return 188 } 189 190 if fn := tt.EarlyCheckResponse; fn != nil { 191 fn("HTTP/1.1", res1) 192 fn("HTTP/2.0", res2) 193 } 194 195 tt.normalizeRes(t, res1, "HTTP/1.1") 196 tt.normalizeRes(t, res2, "HTTP/2.0") 197 res1body, res2body := res1.Body, res2.Body 198 199 eres1 := mostlyCopy(res1) 200 eres2 := mostlyCopy(res2) 201 if !reflect.DeepEqual(eres1, eres2) { 202 t.Errorf("Response headers to handler differed:\nhttp/1 (%v):\n\t%#v\nhttp/2 (%v):\n\t%#v", 203 cst1.ts.URL, eres1, cst2.ts.URL, eres2) 204 } 205 if !reflect.DeepEqual(res1body, res2body) { 206 t.Errorf("Response bodies to handler differed.\nhttp1: %v\nhttp2: %v\n", res1body, res2body) 207 } 208 if fn := tt.CheckResponse; fn != nil { 209 res1.Body, res2.Body = res1body, res2body 210 fn("HTTP/1.1", res1) 211 fn("HTTP/2.0", res2) 212 } 213 } 214 215 func mostlyCopy(r *Response) *Response { 216 c := *r 217 c.Body = nil 218 c.TransferEncoding = nil 219 c.TLS = nil 220 c.Request = nil 221 return &c 222 } 223 224 type slurpResult struct { 225 io.ReadCloser 226 body []byte 227 err error 228 } 229 230 func (sr slurpResult) String() string { return fmt.Sprintf("body %q; err %v", sr.body, sr.err) } 231 232 func (tt h12Compare) normalizeRes(t *testing.T, res *Response, wantProto string) { 233 if res.Proto == wantProto { 234 res.Proto, res.ProtoMajor, res.ProtoMinor = "", 0, 0 235 } else { 236 t.Errorf("got %q response; want %q", res.Proto, wantProto) 237 } 238 slurp, err := ioutil.ReadAll(res.Body) 239 240 res.Body.Close() 241 res.Body = slurpResult{ 242 ReadCloser: ioutil.NopCloser(bytes.NewReader(slurp)), 243 body: slurp, 244 err: err, 245 } 246 for i, v := range res.Header["Date"] { 247 res.Header["Date"][i] = strings.Repeat("x", len(v)) 248 } 249 if res.Request == nil { 250 t.Errorf("for %s, no request", wantProto) 251 } 252 if (res.TLS != nil) != (wantProto == "HTTP/2.0") { 253 t.Errorf("TLS set = %v; want %v", res.TLS != nil, res.TLS == nil) 254 } 255 } 256 257 // Issue 13532 258 func TestH12_HeadContentLengthNoBody(t *testing.T) { 259 h12Compare{ 260 ReqFunc: (*Client).Head, 261 Handler: func(w ResponseWriter, r *Request) { 262 }, 263 }.run(t) 264 } 265 266 func TestH12_HeadContentLengthSmallBody(t *testing.T) { 267 h12Compare{ 268 ReqFunc: (*Client).Head, 269 Handler: func(w ResponseWriter, r *Request) { 270 io.WriteString(w, "small") 271 }, 272 }.run(t) 273 } 274 275 func TestH12_HeadContentLengthLargeBody(t *testing.T) { 276 h12Compare{ 277 ReqFunc: (*Client).Head, 278 Handler: func(w ResponseWriter, r *Request) { 279 chunk := strings.Repeat("x", 512<<10) 280 for i := 0; i < 10; i++ { 281 io.WriteString(w, chunk) 282 } 283 }, 284 }.run(t) 285 } 286 287 func TestH12_200NoBody(t *testing.T) { 288 h12Compare{Handler: func(w ResponseWriter, r *Request) {}}.run(t) 289 } 290 291 func TestH2_204NoBody(t *testing.T) { testH12_noBody(t, 204) } 292 func TestH2_304NoBody(t *testing.T) { testH12_noBody(t, 304) } 293 func TestH2_404NoBody(t *testing.T) { testH12_noBody(t, 404) } 294 295 func testH12_noBody(t *testing.T, status int) { 296 h12Compare{Handler: func(w ResponseWriter, r *Request) { 297 w.WriteHeader(status) 298 }}.run(t) 299 } 300 301 func TestH12_SmallBody(t *testing.T) { 302 h12Compare{Handler: func(w ResponseWriter, r *Request) { 303 io.WriteString(w, "small body") 304 }}.run(t) 305 } 306 307 func TestH12_ExplicitContentLength(t *testing.T) { 308 h12Compare{Handler: func(w ResponseWriter, r *Request) { 309 w.Header().Set("Content-Length", "3") 310 io.WriteString(w, "foo") 311 }}.run(t) 312 } 313 314 func TestH12_FlushBeforeBody(t *testing.T) { 315 h12Compare{Handler: func(w ResponseWriter, r *Request) { 316 w.(Flusher).Flush() 317 io.WriteString(w, "foo") 318 }}.run(t) 319 } 320 321 func TestH12_FlushMidBody(t *testing.T) { 322 h12Compare{Handler: func(w ResponseWriter, r *Request) { 323 io.WriteString(w, "foo") 324 w.(Flusher).Flush() 325 io.WriteString(w, "bar") 326 }}.run(t) 327 } 328 329 func TestH12_Head_ExplicitLen(t *testing.T) { 330 h12Compare{ 331 ReqFunc: (*Client).Head, 332 Handler: func(w ResponseWriter, r *Request) { 333 if r.Method != "HEAD" { 334 t.Errorf("unexpected method %q", r.Method) 335 } 336 w.Header().Set("Content-Length", "1235") 337 }, 338 }.run(t) 339 } 340 341 func TestH12_Head_ImplicitLen(t *testing.T) { 342 h12Compare{ 343 ReqFunc: (*Client).Head, 344 Handler: func(w ResponseWriter, r *Request) { 345 if r.Method != "HEAD" { 346 t.Errorf("unexpected method %q", r.Method) 347 } 348 io.WriteString(w, "foo") 349 }, 350 }.run(t) 351 } 352 353 func TestH12_HandlerWritesTooLittle(t *testing.T) { 354 h12Compare{ 355 Handler: func(w ResponseWriter, r *Request) { 356 w.Header().Set("Content-Length", "3") 357 io.WriteString(w, "12") // one byte short 358 }, 359 CheckResponse: func(proto string, res *Response) { 360 sr, ok := res.Body.(slurpResult) 361 if !ok { 362 t.Errorf("%s body is %T; want slurpResult", proto, res.Body) 363 return 364 } 365 if sr.err != io.ErrUnexpectedEOF { 366 t.Errorf("%s read error = %v; want io.ErrUnexpectedEOF", proto, sr.err) 367 } 368 if string(sr.body) != "12" { 369 t.Errorf("%s body = %q; want %q", proto, sr.body, "12") 370 } 371 }, 372 }.run(t) 373 } 374 375 // Tests that the HTTP/1 and HTTP/2 servers prevent handlers from 376 // writing more than they declared. This test does not test whether 377 // the transport deals with too much data, though, since the server 378 // doesn't make it possible to send bogus data. For those tests, see 379 // transport_test.go (for HTTP/1) or x/net/http2/transport_test.go 380 // (for HTTP/2). 381 func TestH12_HandlerWritesTooMuch(t *testing.T) { 382 h12Compare{ 383 Handler: func(w ResponseWriter, r *Request) { 384 w.Header().Set("Content-Length", "3") 385 w.(Flusher).Flush() 386 io.WriteString(w, "123") 387 w.(Flusher).Flush() 388 n, err := io.WriteString(w, "x") // too many 389 if n > 0 || err == nil { 390 t.Errorf("for proto %q, final write = %v, %v; want 0, some error", r.Proto, n, err) 391 } 392 }, 393 }.run(t) 394 } 395 396 // Verify that both our HTTP/1 and HTTP/2 request and auto-decompress gzip. 397 // Some hosts send gzip even if you don't ask for it; see golang.org/issue/13298 398 func TestH12_AutoGzip(t *testing.T) { 399 h12Compare{ 400 Handler: func(w ResponseWriter, r *Request) { 401 if ae := r.Header.Get("Accept-Encoding"); ae != "gzip" { 402 t.Errorf("%s Accept-Encoding = %q; want gzip", r.Proto, ae) 403 } 404 w.Header().Set("Content-Encoding", "gzip") 405 gz := gzip.NewWriter(w) 406 io.WriteString(gz, "I am some gzipped content. Go go go go go go go go go go go go should compress well.") 407 gz.Close() 408 }, 409 }.run(t) 410 } 411 412 func TestH12_AutoGzip_Disabled(t *testing.T) { 413 h12Compare{ 414 Opts: []interface{}{ 415 func(tr *Transport) { tr.DisableCompression = true }, 416 }, 417 Handler: func(w ResponseWriter, r *Request) { 418 fmt.Fprintf(w, "%q", r.Header["Accept-Encoding"]) 419 if ae := r.Header.Get("Accept-Encoding"); ae != "" { 420 t.Errorf("%s Accept-Encoding = %q; want empty", r.Proto, ae) 421 } 422 }, 423 }.run(t) 424 } 425 426 // Test304Responses verifies that 304s don't declare that they're 427 // chunking in their response headers and aren't allowed to produce 428 // output. 429 func Test304Responses_h1(t *testing.T) { test304Responses(t, h1Mode) } 430 func Test304Responses_h2(t *testing.T) { test304Responses(t, h2Mode) } 431 432 func test304Responses(t *testing.T, h2 bool) { 433 defer afterTest(t) 434 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 435 w.WriteHeader(StatusNotModified) 436 _, err := w.Write([]byte("illegal body")) 437 if err != ErrBodyNotAllowed { 438 t.Errorf("on Write, expected ErrBodyNotAllowed, got %v", err) 439 } 440 })) 441 defer cst.close() 442 res, err := cst.c.Get(cst.ts.URL) 443 if err != nil { 444 t.Fatal(err) 445 } 446 if len(res.TransferEncoding) > 0 { 447 t.Errorf("expected no TransferEncoding; got %v", res.TransferEncoding) 448 } 449 body, err := ioutil.ReadAll(res.Body) 450 if err != nil { 451 t.Error(err) 452 } 453 if len(body) > 0 { 454 t.Errorf("got unexpected body %q", string(body)) 455 } 456 } 457 458 func TestH12_ServerEmptyContentLength(t *testing.T) { 459 h12Compare{ 460 Handler: func(w ResponseWriter, r *Request) { 461 w.Header()["Content-Type"] = []string{""} 462 io.WriteString(w, "<html><body>hi</body></html>") 463 }, 464 }.run(t) 465 } 466 467 func TestH12_RequestContentLength_Known_NonZero(t *testing.T) { 468 h12requestContentLength(t, func() io.Reader { return strings.NewReader("FOUR") }, 4) 469 } 470 471 func TestH12_RequestContentLength_Known_Zero(t *testing.T) { 472 h12requestContentLength(t, func() io.Reader { return nil }, 0) 473 } 474 475 func TestH12_RequestContentLength_Unknown(t *testing.T) { 476 h12requestContentLength(t, func() io.Reader { return struct{ io.Reader }{strings.NewReader("Stuff")} }, -1) 477 } 478 479 func h12requestContentLength(t *testing.T, bodyfn func() io.Reader, wantLen int64) { 480 h12Compare{ 481 Handler: func(w ResponseWriter, r *Request) { 482 w.Header().Set("Got-Length", fmt.Sprint(r.ContentLength)) 483 fmt.Fprintf(w, "Req.ContentLength=%v", r.ContentLength) 484 }, 485 ReqFunc: func(c *Client, url string) (*Response, error) { 486 return c.Post(url, "text/plain", bodyfn()) 487 }, 488 CheckResponse: func(proto string, res *Response) { 489 if got, want := res.Header.Get("Got-Length"), fmt.Sprint(wantLen); got != want { 490 t.Errorf("Proto %q got length %q; want %q", proto, got, want) 491 } 492 }, 493 }.run(t) 494 } 495 496 // Tests that closing the Request.Cancel channel also while still 497 // reading the response body. Issue 13159. 498 func TestCancelRequestMidBody_h1(t *testing.T) { testCancelRequestMidBody(t, h1Mode) } 499 func TestCancelRequestMidBody_h2(t *testing.T) { testCancelRequestMidBody(t, h2Mode) } 500 func testCancelRequestMidBody(t *testing.T, h2 bool) { 501 defer afterTest(t) 502 unblock := make(chan bool) 503 didFlush := make(chan bool, 1) 504 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 505 io.WriteString(w, "Hello") 506 w.(Flusher).Flush() 507 didFlush <- true 508 <-unblock 509 io.WriteString(w, ", world.") 510 })) 511 defer cst.close() 512 defer close(unblock) 513 514 req, _ := NewRequest("GET", cst.ts.URL, nil) 515 cancel := make(chan struct{}) 516 req.Cancel = cancel 517 518 res, err := cst.c.Do(req) 519 if err != nil { 520 t.Fatal(err) 521 } 522 defer res.Body.Close() 523 <-didFlush 524 525 // Read a bit before we cancel. (Issue 13626) 526 // We should have "Hello" at least sitting there. 527 firstRead := make([]byte, 10) 528 n, err := res.Body.Read(firstRead) 529 if err != nil { 530 t.Fatal(err) 531 } 532 firstRead = firstRead[:n] 533 534 close(cancel) 535 536 rest, err := ioutil.ReadAll(res.Body) 537 all := string(firstRead) + string(rest) 538 if all != "Hello" { 539 t.Errorf("Read %q (%q + %q); want Hello", all, firstRead, rest) 540 } 541 if !reflect.DeepEqual(err, ExportErrRequestCanceled) { 542 t.Errorf("ReadAll error = %v; want %v", err, ExportErrRequestCanceled) 543 } 544 } 545 546 // Tests that clients can send trailers to a server and that the server can read them. 547 func TestTrailersClientToServer_h1(t *testing.T) { testTrailersClientToServer(t, h1Mode) } 548 func TestTrailersClientToServer_h2(t *testing.T) { testTrailersClientToServer(t, h2Mode) } 549 550 func testTrailersClientToServer(t *testing.T, h2 bool) { 551 defer afterTest(t) 552 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 553 var decl []string 554 for k := range r.Trailer { 555 decl = append(decl, k) 556 } 557 sort.Strings(decl) 558 559 slurp, err := ioutil.ReadAll(r.Body) 560 if err != nil { 561 t.Errorf("Server reading request body: %v", err) 562 } 563 if string(slurp) != "foo" { 564 t.Errorf("Server read request body %q; want foo", slurp) 565 } 566 if r.Trailer == nil { 567 io.WriteString(w, "nil Trailer") 568 } else { 569 fmt.Fprintf(w, "decl: %v, vals: %s, %s", 570 decl, 571 r.Trailer.Get("Client-Trailer-A"), 572 r.Trailer.Get("Client-Trailer-B")) 573 } 574 })) 575 defer cst.close() 576 577 var req *Request 578 req, _ = NewRequest("POST", cst.ts.URL, io.MultiReader( 579 eofReaderFunc(func() { 580 req.Trailer["Client-Trailer-A"] = []string{"valuea"} 581 }), 582 strings.NewReader("foo"), 583 eofReaderFunc(func() { 584 req.Trailer["Client-Trailer-B"] = []string{"valueb"} 585 }), 586 )) 587 req.Trailer = Header{ 588 "Client-Trailer-A": nil, // to be set later 589 "Client-Trailer-B": nil, // to be set later 590 } 591 req.ContentLength = -1 592 res, err := cst.c.Do(req) 593 if err != nil { 594 t.Fatal(err) 595 } 596 if err := wantBody(res, err, "decl: [Client-Trailer-A Client-Trailer-B], vals: valuea, valueb"); err != nil { 597 t.Error(err) 598 } 599 } 600 601 // Tests that servers send trailers to a client and that the client can read them. 602 func TestTrailersServerToClient_h1(t *testing.T) { testTrailersServerToClient(t, h1Mode, false) } 603 func TestTrailersServerToClient_h2(t *testing.T) { testTrailersServerToClient(t, h2Mode, false) } 604 func TestTrailersServerToClient_Flush_h1(t *testing.T) { testTrailersServerToClient(t, h1Mode, true) } 605 func TestTrailersServerToClient_Flush_h2(t *testing.T) { testTrailersServerToClient(t, h2Mode, true) } 606 607 func testTrailersServerToClient(t *testing.T, h2, flush bool) { 608 defer afterTest(t) 609 const body = "Some body" 610 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 611 w.Header().Set("Trailer", "Server-Trailer-A, Server-Trailer-B") 612 w.Header().Add("Trailer", "Server-Trailer-C") 613 614 io.WriteString(w, body) 615 if flush { 616 w.(Flusher).Flush() 617 } 618 619 // How handlers set Trailers: declare it ahead of time 620 // with the Trailer header, and then mutate the 621 // Header() of those values later, after the response 622 // has been written (we wrote to w above). 623 w.Header().Set("Server-Trailer-A", "valuea") 624 w.Header().Set("Server-Trailer-C", "valuec") // skipping B 625 w.Header().Set("Server-Trailer-NotDeclared", "should be omitted") 626 })) 627 defer cst.close() 628 629 res, err := cst.c.Get(cst.ts.URL) 630 if err != nil { 631 t.Fatal(err) 632 } 633 634 wantHeader := Header{ 635 "Content-Type": {"text/plain; charset=utf-8"}, 636 } 637 wantLen := -1 638 if h2 && !flush { 639 // In HTTP/1.1, any use of trailers forces HTTP/1.1 640 // chunking and a flush at the first write. That's 641 // unnecessary with HTTP/2's framing, so the server 642 // is able to calculate the length while still sending 643 // trailers afterwards. 644 wantLen = len(body) 645 wantHeader["Content-Length"] = []string{fmt.Sprint(wantLen)} 646 } 647 if res.ContentLength != int64(wantLen) { 648 t.Errorf("ContentLength = %v; want %v", res.ContentLength, wantLen) 649 } 650 651 delete(res.Header, "Date") // irrelevant for test 652 if !reflect.DeepEqual(res.Header, wantHeader) { 653 t.Errorf("Header = %v; want %v", res.Header, wantHeader) 654 } 655 656 if got, want := res.Trailer, (Header{ 657 "Server-Trailer-A": nil, 658 "Server-Trailer-B": nil, 659 "Server-Trailer-C": nil, 660 }); !reflect.DeepEqual(got, want) { 661 t.Errorf("Trailer before body read = %v; want %v", got, want) 662 } 663 664 if err := wantBody(res, nil, body); err != nil { 665 t.Fatal(err) 666 } 667 668 if got, want := res.Trailer, (Header{ 669 "Server-Trailer-A": {"valuea"}, 670 "Server-Trailer-B": nil, 671 "Server-Trailer-C": {"valuec"}, 672 }); !reflect.DeepEqual(got, want) { 673 t.Errorf("Trailer after body read = %v; want %v", got, want) 674 } 675 } 676 677 // Don't allow a Body.Read after Body.Close. Issue 13648. 678 func TestResponseBodyReadAfterClose_h1(t *testing.T) { testResponseBodyReadAfterClose(t, h1Mode) } 679 func TestResponseBodyReadAfterClose_h2(t *testing.T) { testResponseBodyReadAfterClose(t, h2Mode) } 680 681 func testResponseBodyReadAfterClose(t *testing.T, h2 bool) { 682 defer afterTest(t) 683 const body = "Some body" 684 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 685 io.WriteString(w, body) 686 })) 687 defer cst.close() 688 res, err := cst.c.Get(cst.ts.URL) 689 if err != nil { 690 t.Fatal(err) 691 } 692 res.Body.Close() 693 data, err := ioutil.ReadAll(res.Body) 694 if len(data) != 0 || err == nil { 695 t.Fatalf("ReadAll returned %q, %v; want error", data, err) 696 } 697 } 698 699 func TestConcurrentReadWriteReqBody_h1(t *testing.T) { testConcurrentReadWriteReqBody(t, h1Mode) } 700 func TestConcurrentReadWriteReqBody_h2(t *testing.T) { testConcurrentReadWriteReqBody(t, h2Mode) } 701 func testConcurrentReadWriteReqBody(t *testing.T, h2 bool) { 702 defer afterTest(t) 703 const reqBody = "some request body" 704 const resBody = "some response body" 705 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 706 var wg sync.WaitGroup 707 wg.Add(2) 708 didRead := make(chan bool, 1) 709 // Read in one goroutine. 710 go func() { 711 defer wg.Done() 712 data, err := ioutil.ReadAll(r.Body) 713 if string(data) != reqBody { 714 t.Errorf("Handler read %q; want %q", data, reqBody) 715 } 716 if err != nil { 717 t.Errorf("Handler Read: %v", err) 718 } 719 didRead <- true 720 }() 721 // Write in another goroutine. 722 go func() { 723 defer wg.Done() 724 if !h2 { 725 // our HTTP/1 implementation intentionally 726 // doesn't permit writes during read (mostly 727 // due to it being undefined); if that is ever 728 // relaxed, change this. 729 <-didRead 730 } 731 io.WriteString(w, resBody) 732 }() 733 wg.Wait() 734 })) 735 defer cst.close() 736 req, _ := NewRequest("POST", cst.ts.URL, strings.NewReader(reqBody)) 737 req.Header.Add("Expect", "100-continue") // just to complicate things 738 res, err := cst.c.Do(req) 739 if err != nil { 740 t.Fatal(err) 741 } 742 data, err := ioutil.ReadAll(res.Body) 743 defer res.Body.Close() 744 if err != nil { 745 t.Fatal(err) 746 } 747 if string(data) != resBody { 748 t.Errorf("read %q; want %q", data, resBody) 749 } 750 } 751 752 func TestConnectRequest_h1(t *testing.T) { testConnectRequest(t, h1Mode) } 753 func TestConnectRequest_h2(t *testing.T) { testConnectRequest(t, h2Mode) } 754 func testConnectRequest(t *testing.T, h2 bool) { 755 defer afterTest(t) 756 gotc := make(chan *Request, 1) 757 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 758 gotc <- r 759 })) 760 defer cst.close() 761 762 u, err := url.Parse(cst.ts.URL) 763 if err != nil { 764 t.Fatal(err) 765 } 766 767 tests := []struct { 768 req *Request 769 want string 770 }{ 771 { 772 req: &Request{ 773 Method: "CONNECT", 774 Header: Header{}, 775 URL: u, 776 }, 777 want: u.Host, 778 }, 779 { 780 req: &Request{ 781 Method: "CONNECT", 782 Header: Header{}, 783 URL: u, 784 Host: "example.com:123", 785 }, 786 want: "example.com:123", 787 }, 788 } 789 790 for i, tt := range tests { 791 res, err := cst.c.Do(tt.req) 792 if err != nil { 793 t.Errorf("%d. RoundTrip = %v", i, err) 794 continue 795 } 796 res.Body.Close() 797 req := <-gotc 798 if req.Method != "CONNECT" { 799 t.Errorf("method = %q; want CONNECT", req.Method) 800 } 801 if req.Host != tt.want { 802 t.Errorf("Host = %q; want %q", req.Host, tt.want) 803 } 804 if req.URL.Host != tt.want { 805 t.Errorf("URL.Host = %q; want %q", req.URL.Host, tt.want) 806 } 807 } 808 } 809 810 func TestTransportUserAgent_h1(t *testing.T) { testTransportUserAgent(t, h1Mode) } 811 func TestTransportUserAgent_h2(t *testing.T) { testTransportUserAgent(t, h2Mode) } 812 func testTransportUserAgent(t *testing.T, h2 bool) { 813 defer afterTest(t) 814 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 815 fmt.Fprintf(w, "%q", r.Header["User-Agent"]) 816 })) 817 defer cst.close() 818 819 either := func(a, b string) string { 820 if h2 { 821 return b 822 } 823 return a 824 } 825 826 tests := []struct { 827 setup func(*Request) 828 want string 829 }{ 830 { 831 func(r *Request) {}, 832 either(`["Go-http-client/1.1"]`, `["Go-http-client/2.0"]`), 833 }, 834 { 835 func(r *Request) { r.Header.Set("User-Agent", "foo/1.2.3") }, 836 `["foo/1.2.3"]`, 837 }, 838 { 839 func(r *Request) { r.Header["User-Agent"] = []string{"single", "or", "multiple"} }, 840 `["single"]`, 841 }, 842 { 843 func(r *Request) { r.Header.Set("User-Agent", "") }, 844 `[]`, 845 }, 846 { 847 func(r *Request) { r.Header["User-Agent"] = nil }, 848 `[]`, 849 }, 850 } 851 for i, tt := range tests { 852 req, _ := NewRequest("GET", cst.ts.URL, nil) 853 tt.setup(req) 854 res, err := cst.c.Do(req) 855 if err != nil { 856 t.Errorf("%d. RoundTrip = %v", i, err) 857 continue 858 } 859 slurp, err := ioutil.ReadAll(res.Body) 860 res.Body.Close() 861 if err != nil { 862 t.Errorf("%d. read body = %v", i, err) 863 continue 864 } 865 if string(slurp) != tt.want { 866 t.Errorf("%d. body mismatch.\n got: %s\nwant: %s\n", i, slurp, tt.want) 867 } 868 } 869 } 870 871 func TestStarRequestFoo_h1(t *testing.T) { testStarRequest(t, "FOO", h1Mode) } 872 func TestStarRequestFoo_h2(t *testing.T) { testStarRequest(t, "FOO", h2Mode) } 873 func TestStarRequestOptions_h1(t *testing.T) { testStarRequest(t, "OPTIONS", h1Mode) } 874 func TestStarRequestOptions_h2(t *testing.T) { testStarRequest(t, "OPTIONS", h2Mode) } 875 func testStarRequest(t *testing.T, method string, h2 bool) { 876 defer afterTest(t) 877 gotc := make(chan *Request, 1) 878 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 879 w.Header().Set("foo", "bar") 880 gotc <- r 881 w.(Flusher).Flush() 882 })) 883 defer cst.close() 884 885 u, err := url.Parse(cst.ts.URL) 886 if err != nil { 887 t.Fatal(err) 888 } 889 u.Path = "*" 890 891 req := &Request{ 892 Method: method, 893 Header: Header{}, 894 URL: u, 895 } 896 897 res, err := cst.c.Do(req) 898 if err != nil { 899 t.Fatalf("RoundTrip = %v", err) 900 } 901 res.Body.Close() 902 903 wantFoo := "bar" 904 wantLen := int64(-1) 905 if method == "OPTIONS" { 906 wantFoo = "" 907 wantLen = 0 908 } 909 if res.StatusCode != 200 { 910 t.Errorf("status code = %v; want %d", res.Status, 200) 911 } 912 if res.ContentLength != wantLen { 913 t.Errorf("content length = %v; want %d", res.ContentLength, wantLen) 914 } 915 if got := res.Header.Get("foo"); got != wantFoo { 916 t.Errorf("response \"foo\" header = %q; want %q", got, wantFoo) 917 } 918 select { 919 case req = <-gotc: 920 default: 921 req = nil 922 } 923 if req == nil { 924 if method != "OPTIONS" { 925 t.Fatalf("handler never got request") 926 } 927 return 928 } 929 if req.Method != method { 930 t.Errorf("method = %q; want %q", req.Method, method) 931 } 932 if req.URL.Path != "*" { 933 t.Errorf("URL.Path = %q; want *", req.URL.Path) 934 } 935 if req.RequestURI != "*" { 936 t.Errorf("RequestURI = %q; want *", req.RequestURI) 937 } 938 } 939 940 // Issue 13957 941 func TestTransportDiscardsUnneededConns(t *testing.T) { 942 setParallel(t) 943 defer afterTest(t) 944 cst := newClientServerTest(t, h2Mode, HandlerFunc(func(w ResponseWriter, r *Request) { 945 fmt.Fprintf(w, "Hello, %v", r.RemoteAddr) 946 })) 947 defer cst.close() 948 949 var numOpen, numClose int32 // atomic 950 951 tlsConfig := &tls.Config{InsecureSkipVerify: true} 952 tr := &Transport{ 953 TLSClientConfig: tlsConfig, 954 DialTLS: func(_, addr string) (net.Conn, error) { 955 time.Sleep(10 * time.Millisecond) 956 rc, err := net.Dial("tcp", addr) 957 if err != nil { 958 return nil, err 959 } 960 atomic.AddInt32(&numOpen, 1) 961 c := noteCloseConn{rc, func() { atomic.AddInt32(&numClose, 1) }} 962 return tls.Client(c, tlsConfig), nil 963 }, 964 } 965 if err := ExportHttp2ConfigureTransport(tr); err != nil { 966 t.Fatal(err) 967 } 968 defer tr.CloseIdleConnections() 969 970 c := &Client{Transport: tr} 971 972 const N = 10 973 gotBody := make(chan string, N) 974 var wg sync.WaitGroup 975 for i := 0; i < N; i++ { 976 wg.Add(1) 977 go func() { 978 defer wg.Done() 979 resp, err := c.Get(cst.ts.URL) 980 if err != nil { 981 t.Errorf("Get: %v", err) 982 return 983 } 984 defer resp.Body.Close() 985 slurp, err := ioutil.ReadAll(resp.Body) 986 if err != nil { 987 t.Error(err) 988 } 989 gotBody <- string(slurp) 990 }() 991 } 992 wg.Wait() 993 close(gotBody) 994 995 var last string 996 for got := range gotBody { 997 if last == "" { 998 last = got 999 continue 1000 } 1001 if got != last { 1002 t.Errorf("Response body changed: %q -> %q", last, got) 1003 } 1004 } 1005 1006 var open, close int32 1007 for i := 0; i < 150; i++ { 1008 open, close = atomic.LoadInt32(&numOpen), atomic.LoadInt32(&numClose) 1009 if open < 1 { 1010 t.Fatalf("open = %d; want at least", open) 1011 } 1012 if close == open-1 { 1013 // Success 1014 return 1015 } 1016 time.Sleep(10 * time.Millisecond) 1017 } 1018 t.Errorf("%d connections opened, %d closed; want %d to close", open, close, open-1) 1019 } 1020 1021 // tests that Transport doesn't retain a pointer to the provided request. 1022 func TestTransportGCRequest_Body_h1(t *testing.T) { testTransportGCRequest(t, h1Mode, true) } 1023 func TestTransportGCRequest_Body_h2(t *testing.T) { testTransportGCRequest(t, h2Mode, true) } 1024 func TestTransportGCRequest_NoBody_h1(t *testing.T) { testTransportGCRequest(t, h1Mode, false) } 1025 func TestTransportGCRequest_NoBody_h2(t *testing.T) { testTransportGCRequest(t, h2Mode, false) } 1026 func testTransportGCRequest(t *testing.T, h2, body bool) { 1027 setParallel(t) 1028 defer afterTest(t) 1029 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 1030 ioutil.ReadAll(r.Body) 1031 if body { 1032 io.WriteString(w, "Hello.") 1033 } 1034 })) 1035 defer cst.close() 1036 1037 didGC := make(chan struct{}) 1038 (func() { 1039 body := strings.NewReader("some body") 1040 req, _ := NewRequest("POST", cst.ts.URL, body) 1041 runtime.SetFinalizer(req, func(*Request) { close(didGC) }) 1042 res, err := cst.c.Do(req) 1043 if err != nil { 1044 t.Fatal(err) 1045 } 1046 if _, err := ioutil.ReadAll(res.Body); err != nil { 1047 t.Fatal(err) 1048 } 1049 if err := res.Body.Close(); err != nil { 1050 t.Fatal(err) 1051 } 1052 })() 1053 timeout := time.NewTimer(5 * time.Second) 1054 defer timeout.Stop() 1055 for { 1056 select { 1057 case <-didGC: 1058 return 1059 case <-time.After(100 * time.Millisecond): 1060 runtime.GC() 1061 case <-timeout.C: 1062 t.Fatal("never saw GC of request") 1063 } 1064 } 1065 } 1066 1067 func TestTransportRejectsInvalidHeaders_h1(t *testing.T) { 1068 testTransportRejectsInvalidHeaders(t, h1Mode) 1069 } 1070 func TestTransportRejectsInvalidHeaders_h2(t *testing.T) { 1071 testTransportRejectsInvalidHeaders(t, h2Mode) 1072 } 1073 func testTransportRejectsInvalidHeaders(t *testing.T, h2 bool) { 1074 setParallel(t) 1075 defer afterTest(t) 1076 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 1077 fmt.Fprintf(w, "Handler saw headers: %q", r.Header) 1078 })) 1079 defer cst.close() 1080 cst.tr.DisableKeepAlives = true 1081 1082 tests := []struct { 1083 key, val string 1084 ok bool 1085 }{ 1086 {"Foo", "capital-key", true}, // verify h2 allows capital keys 1087 {"Foo", "foo\x00bar", false}, // \x00 byte in value not allowed 1088 {"Foo", "two\nlines", false}, // \n byte in value not allowed 1089 {"bogus\nkey", "v", false}, // \n byte also not allowed in key 1090 {"A space", "v", false}, // spaces in keys not allowed 1091 {"имя", "v", false}, // key must be ascii 1092 {"name", "валю", true}, // value may be non-ascii 1093 {"", "v", false}, // key must be non-empty 1094 {"k", "", true}, // value may be empty 1095 } 1096 for _, tt := range tests { 1097 dialedc := make(chan bool, 1) 1098 cst.tr.Dial = func(netw, addr string) (net.Conn, error) { 1099 dialedc <- true 1100 return net.Dial(netw, addr) 1101 } 1102 req, _ := NewRequest("GET", cst.ts.URL, nil) 1103 req.Header[tt.key] = []string{tt.val} 1104 res, err := cst.c.Do(req) 1105 var body []byte 1106 if err == nil { 1107 body, _ = ioutil.ReadAll(res.Body) 1108 res.Body.Close() 1109 } 1110 var dialed bool 1111 select { 1112 case <-dialedc: 1113 dialed = true 1114 default: 1115 } 1116 1117 if !tt.ok && dialed { 1118 t.Errorf("For key %q, value %q, transport dialed. Expected local failure. Response was: (%v, %v)\nServer replied with: %s", tt.key, tt.val, res, err, body) 1119 } else if (err == nil) != tt.ok { 1120 t.Errorf("For key %q, value %q; got err = %v; want ok=%v", tt.key, tt.val, err, tt.ok) 1121 } 1122 } 1123 } 1124 1125 // Tests that we support bogus under-100 HTTP statuses, because we historically 1126 // have. This might change at some point, but not yet in Go 1.6. 1127 func TestBogusStatusWorks_h1(t *testing.T) { testBogusStatusWorks(t, h1Mode) } 1128 func TestBogusStatusWorks_h2(t *testing.T) { testBogusStatusWorks(t, h2Mode) } 1129 func testBogusStatusWorks(t *testing.T, h2 bool) { 1130 defer afterTest(t) 1131 const code = 7 1132 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 1133 w.WriteHeader(code) 1134 })) 1135 defer cst.close() 1136 1137 res, err := cst.c.Get(cst.ts.URL) 1138 if err != nil { 1139 t.Fatal(err) 1140 } 1141 if res.StatusCode != code { 1142 t.Errorf("StatusCode = %d; want %d", res.StatusCode, code) 1143 } 1144 } 1145 1146 func TestInterruptWithPanic_h1(t *testing.T) { testInterruptWithPanic(t, h1Mode) } 1147 func TestInterruptWithPanic_h2(t *testing.T) { testInterruptWithPanic(t, h2Mode) } 1148 func testInterruptWithPanic(t *testing.T, h2 bool) { 1149 log.SetOutput(ioutil.Discard) // is noisy otherwise 1150 defer log.SetOutput(os.Stderr) 1151 1152 const msg = "hello" 1153 defer afterTest(t) 1154 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 1155 io.WriteString(w, msg) 1156 w.(Flusher).Flush() 1157 panic("no more") 1158 })) 1159 defer cst.close() 1160 res, err := cst.c.Get(cst.ts.URL) 1161 if err != nil { 1162 t.Fatal(err) 1163 } 1164 defer res.Body.Close() 1165 slurp, err := ioutil.ReadAll(res.Body) 1166 if string(slurp) != msg { 1167 t.Errorf("client read %q; want %q", slurp, msg) 1168 } 1169 if err == nil { 1170 t.Errorf("client read all successfully; want some error") 1171 } 1172 } 1173 1174 // Issue 15366 1175 func TestH12_AutoGzipWithDumpResponse(t *testing.T) { 1176 h12Compare{ 1177 Handler: func(w ResponseWriter, r *Request) { 1178 h := w.Header() 1179 h.Set("Content-Encoding", "gzip") 1180 h.Set("Content-Length", "23") 1181 h.Set("Connection", "keep-alive") 1182 io.WriteString(w, "\x1f\x8b\b\x00\x00\x00\x00\x00\x00\x00s\xf3\xf7\a\x00\xab'\xd4\x1a\x03\x00\x00\x00") 1183 }, 1184 EarlyCheckResponse: func(proto string, res *Response) { 1185 if !res.Uncompressed { 1186 t.Errorf("%s: expected Uncompressed to be set", proto) 1187 } 1188 dump, err := httputil.DumpResponse(res, true) 1189 if err != nil { 1190 t.Errorf("%s: DumpResponse: %v", proto, err) 1191 return 1192 } 1193 if strings.Contains(string(dump), "Connection: close") { 1194 t.Errorf("%s: should not see \"Connection: close\" in dump; got:\n%s", proto, dump) 1195 } 1196 if !strings.Contains(string(dump), "FOO") { 1197 t.Errorf("%s: should see \"FOO\" in response; got:\n%s", proto, dump) 1198 } 1199 }, 1200 }.run(t) 1201 } 1202 1203 // Issue 14607 1204 func TestCloseIdleConnections_h1(t *testing.T) { testCloseIdleConnections(t, h1Mode) } 1205 func TestCloseIdleConnections_h2(t *testing.T) { testCloseIdleConnections(t, h2Mode) } 1206 func testCloseIdleConnections(t *testing.T, h2 bool) { 1207 setParallel(t) 1208 defer afterTest(t) 1209 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 1210 w.Header().Set("X-Addr", r.RemoteAddr) 1211 })) 1212 defer cst.close() 1213 get := func() string { 1214 res, err := cst.c.Get(cst.ts.URL) 1215 if err != nil { 1216 t.Fatal(err) 1217 } 1218 res.Body.Close() 1219 v := res.Header.Get("X-Addr") 1220 if v == "" { 1221 t.Fatal("didn't get X-Addr") 1222 } 1223 return v 1224 } 1225 a1 := get() 1226 cst.tr.CloseIdleConnections() 1227 a2 := get() 1228 if a1 == a2 { 1229 t.Errorf("didn't close connection") 1230 } 1231 } 1232 1233 type noteCloseConn struct { 1234 net.Conn 1235 closeFunc func() 1236 } 1237 1238 func (x noteCloseConn) Close() error { 1239 x.closeFunc() 1240 return x.Conn.Close() 1241 } 1242 1243 type testErrorReader struct{ t *testing.T } 1244 1245 func (r testErrorReader) Read(p []byte) (n int, err error) { 1246 r.t.Error("unexpected Read call") 1247 return 0, io.EOF 1248 } 1249 1250 func TestNoSniffExpectRequestBody_h1(t *testing.T) { testNoSniffExpectRequestBody(t, h1Mode) } 1251 func TestNoSniffExpectRequestBody_h2(t *testing.T) { testNoSniffExpectRequestBody(t, h2Mode) } 1252 1253 func testNoSniffExpectRequestBody(t *testing.T, h2 bool) { 1254 defer afterTest(t) 1255 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 1256 w.WriteHeader(StatusUnauthorized) 1257 })) 1258 defer cst.close() 1259 1260 // Set ExpectContinueTimeout non-zero so RoundTrip won't try to write it. 1261 cst.tr.ExpectContinueTimeout = 10 * time.Second 1262 1263 req, err := NewRequest("POST", cst.ts.URL, testErrorReader{t}) 1264 if err != nil { 1265 t.Fatal(err) 1266 } 1267 req.ContentLength = 0 // so transport is tempted to sniff it 1268 req.Header.Set("Expect", "100-continue") 1269 res, err := cst.tr.RoundTrip(req) 1270 if err != nil { 1271 t.Fatal(err) 1272 } 1273 defer res.Body.Close() 1274 if res.StatusCode != StatusUnauthorized { 1275 t.Errorf("status code = %v; want %v", res.StatusCode, StatusUnauthorized) 1276 } 1277 } 1278 1279 func TestServerUndeclaredTrailers_h1(t *testing.T) { testServerUndeclaredTrailers(t, h1Mode) } 1280 func TestServerUndeclaredTrailers_h2(t *testing.T) { testServerUndeclaredTrailers(t, h2Mode) } 1281 func testServerUndeclaredTrailers(t *testing.T, h2 bool) { 1282 defer afterTest(t) 1283 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 1284 w.Header().Set("Foo", "Bar") 1285 w.Header().Set("Trailer:Foo", "Baz") 1286 w.(Flusher).Flush() 1287 w.Header().Add("Trailer:Foo", "Baz2") 1288 w.Header().Set("Trailer:Bar", "Quux") 1289 })) 1290 defer cst.close() 1291 res, err := cst.c.Get(cst.ts.URL) 1292 if err != nil { 1293 t.Fatal(err) 1294 } 1295 if _, err := io.Copy(ioutil.Discard, res.Body); err != nil { 1296 t.Fatal(err) 1297 } 1298 res.Body.Close() 1299 delete(res.Header, "Date") 1300 delete(res.Header, "Content-Type") 1301 1302 if want := (Header{"Foo": {"Bar"}}); !reflect.DeepEqual(res.Header, want) { 1303 t.Errorf("Header = %#v; want %#v", res.Header, want) 1304 } 1305 if want := (Header{"Foo": {"Baz", "Baz2"}, "Bar": {"Quux"}}); !reflect.DeepEqual(res.Trailer, want) { 1306 t.Errorf("Trailer = %#v; want %#v", res.Trailer, want) 1307 } 1308 }