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