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