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