Source file
src/net/http/serve_test.go
1
2
3
4
5
6
7 package http_test
8
9 import (
10 "bufio"
11 "bytes"
12 "compress/gzip"
13 "compress/zlib"
14 "context"
15 crand "crypto/rand"
16 "crypto/tls"
17 "crypto/x509"
18 "encoding/json"
19 "errors"
20 "fmt"
21 "internal/testenv"
22 "io"
23 "log"
24 "math/rand"
25 "mime/multipart"
26 "net"
27 . "net/http"
28 "net/http/httptest"
29 "net/http/httptrace"
30 "net/http/httputil"
31 "net/http/internal"
32 "net/http/internal/testcert"
33 "net/url"
34 "os"
35 "path/filepath"
36 "reflect"
37 "regexp"
38 "runtime"
39 "slices"
40 "strconv"
41 "strings"
42 "sync"
43 "sync/atomic"
44 "syscall"
45 "testing"
46 "testing/synctest"
47 "time"
48 )
49
50 type dummyAddr string
51 type oneConnListener struct {
52 conn net.Conn
53 }
54
55 func (l *oneConnListener) Accept() (c net.Conn, err error) {
56 c = l.conn
57 if c == nil {
58 err = io.EOF
59 return
60 }
61 err = nil
62 l.conn = nil
63 return
64 }
65
66 func (l *oneConnListener) Close() error {
67 return nil
68 }
69
70 func (l *oneConnListener) Addr() net.Addr {
71 return dummyAddr("test-address")
72 }
73
74 func (a dummyAddr) Network() string {
75 return string(a)
76 }
77
78 func (a dummyAddr) String() string {
79 return string(a)
80 }
81
82 type noopConn struct{}
83
84 func (noopConn) LocalAddr() net.Addr { return dummyAddr("local-addr") }
85 func (noopConn) RemoteAddr() net.Addr { return dummyAddr("remote-addr") }
86 func (noopConn) SetDeadline(t time.Time) error { return nil }
87 func (noopConn) SetReadDeadline(t time.Time) error { return nil }
88 func (noopConn) SetWriteDeadline(t time.Time) error { return nil }
89
90 type rwTestConn struct {
91 io.Reader
92 io.Writer
93 noopConn
94
95 closeFunc func() error
96 closec chan bool
97 }
98
99 func (c *rwTestConn) Close() error {
100 if c.closeFunc != nil {
101 return c.closeFunc()
102 }
103 select {
104 case c.closec <- true:
105 default:
106 }
107 return nil
108 }
109
110 type testConn struct {
111 readMu sync.Mutex
112 readBuf bytes.Buffer
113 writeBuf bytes.Buffer
114 closec chan bool
115 noopConn
116 }
117
118 func newTestConn() *testConn {
119 return &testConn{closec: make(chan bool, 1)}
120 }
121
122 func (c *testConn) Read(b []byte) (int, error) {
123 c.readMu.Lock()
124 defer c.readMu.Unlock()
125 return c.readBuf.Read(b)
126 }
127
128 func (c *testConn) Write(b []byte) (int, error) {
129 return c.writeBuf.Write(b)
130 }
131
132 func (c *testConn) Close() error {
133 select {
134 case c.closec <- true:
135 default:
136 }
137 return nil
138 }
139
140
141
142 func reqBytes(req string) []byte {
143 return []byte(strings.ReplaceAll(strings.TrimSpace(req), "\n", "\r\n") + "\r\n\r\n")
144 }
145
146 type handlerTest struct {
147 logbuf bytes.Buffer
148 handler Handler
149 }
150
151 func newHandlerTest(h Handler) handlerTest {
152 return handlerTest{handler: h}
153 }
154
155 func (ht *handlerTest) rawResponse(req string) string {
156 reqb := reqBytes(req)
157 var output strings.Builder
158 conn := &rwTestConn{
159 Reader: bytes.NewReader(reqb),
160 Writer: &output,
161 closec: make(chan bool, 1),
162 }
163 ln := &oneConnListener{conn: conn}
164 srv := &Server{
165 ErrorLog: log.New(&ht.logbuf, "", 0),
166 Handler: ht.handler,
167 }
168 go srv.Serve(ln)
169 <-conn.closec
170 return output.String()
171 }
172
173 func TestConsumingBodyOnNextConn(t *testing.T) {
174 t.Parallel()
175 defer afterTest(t)
176 conn := new(testConn)
177 for i := 0; i < 2; i++ {
178 conn.readBuf.Write([]byte(
179 "POST / HTTP/1.1\r\n" +
180 "Host: test\r\n" +
181 "Content-Length: 11\r\n" +
182 "\r\n" +
183 "foo=1&bar=1"))
184 }
185
186 reqNum := 0
187 ch := make(chan *Request)
188 servech := make(chan error)
189 listener := &oneConnListener{conn}
190 handler := func(res ResponseWriter, req *Request) {
191 reqNum++
192 ch <- req
193 }
194
195 go func() {
196 servech <- Serve(listener, HandlerFunc(handler))
197 }()
198
199 var req *Request
200 req = <-ch
201 if req == nil {
202 t.Fatal("Got nil first request.")
203 }
204 if req.Method != "POST" {
205 t.Errorf("For request #1's method, got %q; expected %q",
206 req.Method, "POST")
207 }
208
209 req = <-ch
210 if req == nil {
211 t.Fatal("Got nil first request.")
212 }
213 if req.Method != "POST" {
214 t.Errorf("For request #2's method, got %q; expected %q",
215 req.Method, "POST")
216 }
217
218 if serveerr := <-servech; serveerr != io.EOF {
219 t.Errorf("Serve returned %q; expected EOF", serveerr)
220 }
221 }
222
223 type stringHandler string
224
225 func (s stringHandler) ServeHTTP(w ResponseWriter, r *Request) {
226 w.Header().Set("Result", string(s))
227 }
228
229 var handlers = []struct {
230 pattern string
231 msg string
232 }{
233 {"/", "Default"},
234 {"/someDir/", "someDir"},
235 {"/#/", "hash"},
236 {"someHost.com/someDir/", "someHost.com/someDir"},
237 }
238
239 var vtests = []struct {
240 url string
241 expected string
242 }{
243 {"http://localhost/someDir/apage", "someDir"},
244 {"http://localhost/%23/apage", "hash"},
245 {"http://localhost/otherDir/apage", "Default"},
246 {"http://someHost.com/someDir/apage", "someHost.com/someDir"},
247 {"http://otherHost.com/someDir/apage", "someDir"},
248 {"http://otherHost.com/aDir/apage", "Default"},
249
250 {"http://localhost/someDir", "/someDir/"},
251 {"http://localhost/%23", "/%23/"},
252 {"http://someHost.com/someDir", "/someDir/"},
253 }
254
255 func TestHostHandlers(t *testing.T) { run(t, testHostHandlers, []testMode{http1Mode}) }
256 func testHostHandlers(t *testing.T, mode testMode) {
257 mux := NewServeMux()
258 for _, h := range handlers {
259 mux.Handle(h.pattern, stringHandler(h.msg))
260 }
261 ts := newClientServerTest(t, mode, mux).ts
262
263 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
264 if err != nil {
265 t.Fatal(err)
266 }
267 defer conn.Close()
268 cc := httputil.NewClientConn(conn, nil)
269 for _, vt := range vtests {
270 var r *Response
271 var req Request
272 if req.URL, err = url.Parse(vt.url); err != nil {
273 t.Errorf("cannot parse url: %v", err)
274 continue
275 }
276 if err := cc.Write(&req); err != nil {
277 t.Errorf("writing request: %v", err)
278 continue
279 }
280 r, err := cc.Read(&req)
281 if err != nil {
282 t.Errorf("reading response: %v", err)
283 continue
284 }
285 switch r.StatusCode {
286 case StatusOK:
287 s := r.Header.Get("Result")
288 if s != vt.expected {
289 t.Errorf("Get(%q) = %q, want %q", vt.url, s, vt.expected)
290 }
291 case StatusTemporaryRedirect:
292 s := r.Header.Get("Location")
293 if s != vt.expected {
294 t.Errorf("Get(%q) = %q, want %q", vt.url, s, vt.expected)
295 }
296 default:
297 t.Errorf("Get(%q) unhandled status code %d", vt.url, r.StatusCode)
298 }
299 }
300 }
301
302 var serveMuxRegister = []struct {
303 pattern string
304 h Handler
305 }{
306 {"/dir/", serve(200)},
307 {"/search", serve(201)},
308 {"codesearch.google.com/search", serve(202)},
309 {"codesearch.google.com/", serve(203)},
310 {"example.com/", HandlerFunc(checkQueryStringHandler)},
311 }
312
313
314 func serve(code int) HandlerFunc {
315 return func(w ResponseWriter, r *Request) {
316 w.WriteHeader(code)
317 }
318 }
319
320
321
322
323 func checkQueryStringHandler(w ResponseWriter, r *Request) {
324 u := *r.URL
325 u.Scheme = "http"
326 u.Host = r.Host
327 u.RawQuery = ""
328 if "http://"+r.URL.RawQuery == u.String() {
329 w.WriteHeader(200)
330 } else {
331 w.WriteHeader(500)
332 }
333 }
334
335 var serveMuxTests = []struct {
336 method string
337 host string
338 path string
339 code int
340 pattern string
341 }{
342 {"GET", "google.com", "/", 404, ""},
343 {"GET", "google.com", "/dir", 307, "/dir/"},
344 {"GET", "google.com", "/dir/", 200, "/dir/"},
345 {"GET", "google.com", "/dir/file", 200, "/dir/"},
346 {"GET", "google.com", "/search", 201, "/search"},
347 {"GET", "google.com", "/search/", 404, ""},
348 {"GET", "google.com", "/search/foo", 404, ""},
349 {"GET", "codesearch.google.com", "/search", 202, "codesearch.google.com/search"},
350 {"GET", "codesearch.google.com", "/search/", 203, "codesearch.google.com/"},
351 {"GET", "codesearch.google.com", "/search/foo", 203, "codesearch.google.com/"},
352 {"GET", "codesearch.google.com", "/", 203, "codesearch.google.com/"},
353 {"GET", "codesearch.google.com:443", "/", 203, "codesearch.google.com/"},
354 {"GET", "images.google.com", "/search", 201, "/search"},
355 {"GET", "images.google.com", "/search/", 404, ""},
356 {"GET", "images.google.com", "/search/foo", 404, ""},
357 {"GET", "google.com", "/../search", 307, "/search"},
358 {"GET", "google.com", "/dir/..", 307, ""},
359 {"GET", "google.com", "/dir/..", 307, ""},
360 {"GET", "google.com", "/dir/./file", 307, "/dir/"},
361
362
363
364 {"CONNECT", "google.com", "/dir", 307, "/dir/"},
365 {"CONNECT", "google.com", "/../search", 404, ""},
366 {"CONNECT", "google.com", "/dir/..", 200, "/dir/"},
367 {"CONNECT", "google.com", "/dir/..", 200, "/dir/"},
368 {"CONNECT", "google.com", "/dir/./file", 200, "/dir/"},
369 }
370
371 func TestServeMuxHandler(t *testing.T) {
372 setParallel(t)
373 mux := NewServeMux()
374 for _, e := range serveMuxRegister {
375 mux.Handle(e.pattern, e.h)
376 }
377
378 for _, tt := range serveMuxTests {
379 r := &Request{
380 Method: tt.method,
381 Host: tt.host,
382 URL: &url.URL{
383 Path: tt.path,
384 },
385 }
386 h, pattern := mux.Handler(r)
387 rr := httptest.NewRecorder()
388 h.ServeHTTP(rr, r)
389 if pattern != tt.pattern || rr.Code != tt.code {
390 t.Errorf("%s %s %s = %d, %q, want %d, %q", tt.method, tt.host, tt.path, rr.Code, pattern, tt.code, tt.pattern)
391 }
392 }
393 }
394
395
396 func TestServeMuxHandlerTrailingSlash(t *testing.T) {
397 setParallel(t)
398 mux := NewServeMux()
399 const original = "/{x}/"
400 mux.Handle(original, NotFoundHandler())
401 r, _ := NewRequest("POST", "/foo", nil)
402 _, p := mux.Handler(r)
403 if p != original {
404 t.Errorf("got %q, want %q", p, original)
405 }
406 }
407
408
409 func TestServeMuxHandleFuncWithNilHandler(t *testing.T) {
410 setParallel(t)
411 defer func() {
412 if err := recover(); err == nil {
413 t.Error("expected call to mux.HandleFunc to panic")
414 }
415 }()
416 mux := NewServeMux()
417 mux.HandleFunc("/", nil)
418 }
419
420 var serveMuxTests2 = []struct {
421 method string
422 host string
423 url string
424 code int
425 redirOk bool
426 }{
427 {"GET", "google.com", "/", 404, false},
428 {"GET", "example.com", "/test/?example.com/test/", 200, false},
429 {"GET", "example.com", "test/?example.com/test/", 200, true},
430 }
431
432
433
434 func TestServeMuxHandlerRedirects(t *testing.T) {
435 setParallel(t)
436 mux := NewServeMux()
437 for _, e := range serveMuxRegister {
438 mux.Handle(e.pattern, e.h)
439 }
440
441 for _, tt := range serveMuxTests2 {
442 tries := 1
443 turl := tt.url
444 for {
445 u, e := url.Parse(turl)
446 if e != nil {
447 t.Fatal(e)
448 }
449 r := &Request{
450 Method: tt.method,
451 Host: tt.host,
452 URL: u,
453 }
454 h, _ := mux.Handler(r)
455 rr := httptest.NewRecorder()
456 h.ServeHTTP(rr, r)
457 if rr.Code != 307 {
458 if rr.Code != tt.code {
459 t.Errorf("%s %s %s = %d, want %d", tt.method, tt.host, tt.url, rr.Code, tt.code)
460 }
461 break
462 }
463 if !tt.redirOk {
464 t.Errorf("%s %s %s, unexpected redirect", tt.method, tt.host, tt.url)
465 break
466 }
467 turl = rr.HeaderMap.Get("Location")
468 tries--
469 }
470 if tries < 0 {
471 t.Errorf("%s %s %s, too many redirects", tt.method, tt.host, tt.url)
472 }
473 }
474 }
475
476 func TestServeMuxHandlerRedirectPost(t *testing.T) {
477 setParallel(t)
478 mux := NewServeMux()
479 mux.HandleFunc("POST /test/", func(w ResponseWriter, r *Request) {
480 w.WriteHeader(200)
481 })
482
483 var code, retries int
484 startURL := "http://example.com/test"
485 reqURL := startURL
486 for retries = 0; retries <= 1; retries++ {
487 r := httptest.NewRequest("POST", reqURL, strings.NewReader("hello world"))
488 h, _ := mux.Handler(r)
489 rr := httptest.NewRecorder()
490 h.ServeHTTP(rr, r)
491 code = rr.Code
492 switch rr.Code {
493 case 307:
494 reqURL = rr.Result().Header.Get("Location")
495 continue
496 case 200:
497
498 default:
499 t.Errorf("unhandled response code: %v", rr.Code)
500 }
501 }
502 if code != 200 {
503 t.Errorf("POST %s = %d after %d retries, want = 200", startURL, code, retries)
504 }
505 }
506
507
508 func TestMuxRedirectLeadingSlashes(t *testing.T) {
509 setParallel(t)
510 paths := []string{"//foo.txt", "///foo.txt", "/../../foo.txt"}
511 for _, path := range paths {
512 req, err := ReadRequest(bufio.NewReader(strings.NewReader("GET " + path + " HTTP/1.1\r\nHost: test\r\n\r\n")))
513 if err != nil {
514 t.Errorf("%s", err)
515 }
516 mux := NewServeMux()
517 resp := httptest.NewRecorder()
518
519 mux.ServeHTTP(resp, req)
520
521 if loc, expected := resp.Header().Get("Location"), "/foo.txt"; loc != expected {
522 t.Errorf("Expected Location header set to %q; got %q", expected, loc)
523 return
524 }
525
526 if code, expected := resp.Code, StatusTemporaryRedirect; code != expected {
527 t.Errorf("Expected response code of StatusPermanentRedirect; got %d", code)
528 return
529 }
530 }
531 }
532
533
534
535
536
537 func TestServeWithSlashRedirectKeepsQueryString(t *testing.T) {
538 run(t, testServeWithSlashRedirectKeepsQueryString, []testMode{http1Mode})
539 }
540 func testServeWithSlashRedirectKeepsQueryString(t *testing.T, mode testMode) {
541 writeBackQuery := func(w ResponseWriter, r *Request) {
542 fmt.Fprintf(w, "%s", r.URL.RawQuery)
543 }
544
545 mux := NewServeMux()
546 mux.HandleFunc("/testOne", writeBackQuery)
547 mux.HandleFunc("/testTwo/", writeBackQuery)
548 mux.HandleFunc("/testThree", writeBackQuery)
549 mux.HandleFunc("/testThree/", func(w ResponseWriter, r *Request) {
550 fmt.Fprintf(w, "%s:bar", r.URL.RawQuery)
551 })
552
553 ts := newClientServerTest(t, mode, mux).ts
554
555 tests := [...]struct {
556 path string
557 method string
558 want string
559 statusOk bool
560 }{
561 0: {"/testOne?this=that", "GET", "this=that", true},
562 1: {"/testTwo?foo=bar", "GET", "foo=bar", true},
563 2: {"/testTwo?a=1&b=2&a=3", "GET", "a=1&b=2&a=3", true},
564 3: {"/testTwo?", "GET", "", true},
565 4: {"/testThree?foo", "GET", "foo", true},
566 5: {"/testThree/?foo", "GET", "foo:bar", true},
567 6: {"/testThree?foo", "CONNECT", "foo", true},
568 7: {"/testThree/?foo", "CONNECT", "foo:bar", true},
569
570
571 8: {"/testOne/foo/..?foo", "GET", "foo", true},
572 9: {"/testOne/foo/..?foo", "CONNECT", "404 page not found\n", false},
573 }
574
575 for i, tt := range tests {
576 req, _ := NewRequest(tt.method, ts.URL+tt.path, nil)
577 res, err := ts.Client().Do(req)
578 if err != nil {
579 continue
580 }
581 slurp, _ := io.ReadAll(res.Body)
582 res.Body.Close()
583 if !tt.statusOk {
584 if got, want := res.StatusCode, 404; got != want {
585 t.Errorf("#%d: Status = %d; want = %d", i, got, want)
586 }
587 }
588 if got, want := string(slurp), tt.want; got != want {
589 t.Errorf("#%d: Body = %q; want = %q", i, got, want)
590 }
591 }
592 }
593
594 func TestServeWithSlashRedirectForHostPatterns(t *testing.T) {
595 setParallel(t)
596
597 mux := NewServeMux()
598 mux.Handle("example.com/pkg/foo/", stringHandler("example.com/pkg/foo/"))
599 mux.Handle("example.com/pkg/bar", stringHandler("example.com/pkg/bar"))
600 mux.Handle("example.com/pkg/bar/", stringHandler("example.com/pkg/bar/"))
601 mux.Handle("example.com:3000/pkg/connect/", stringHandler("example.com:3000/pkg/connect/"))
602 mux.Handle("example.com:9000/", stringHandler("example.com:9000/"))
603 mux.Handle("/pkg/baz/", stringHandler("/pkg/baz/"))
604
605 tests := []struct {
606 method string
607 url string
608 code int
609 loc string
610 want string
611 }{
612 {"GET", "http://example.com/", 404, "", ""},
613 {"GET", "http://example.com/pkg/foo", 307, "/pkg/foo/", ""},
614 {"GET", "http://example.com/pkg/bar", 200, "", "example.com/pkg/bar"},
615 {"GET", "http://example.com/pkg/bar/", 200, "", "example.com/pkg/bar/"},
616 {"GET", "http://example.com/pkg/baz", 307, "/pkg/baz/", ""},
617 {"GET", "http://example.com:3000/pkg/foo", 307, "/pkg/foo/", ""},
618 {"CONNECT", "http://example.com/", 404, "", ""},
619 {"CONNECT", "http://example.com:3000/", 404, "", ""},
620 {"CONNECT", "http://example.com:9000/", 200, "", "example.com:9000/"},
621 {"CONNECT", "http://example.com/pkg/foo", 307, "/pkg/foo/", ""},
622 {"CONNECT", "http://example.com:3000/pkg/foo", 404, "", ""},
623 {"CONNECT", "http://example.com:3000/pkg/baz", 307, "/pkg/baz/", ""},
624 {"CONNECT", "http://example.com:3000/pkg/connect", 307, "/pkg/connect/", ""},
625 }
626
627 for i, tt := range tests {
628 req, _ := NewRequest(tt.method, tt.url, nil)
629 w := httptest.NewRecorder()
630 mux.ServeHTTP(w, req)
631
632 if got, want := w.Code, tt.code; got != want {
633 t.Errorf("#%d: Status = %d; want = %d", i, got, want)
634 }
635
636 if tt.code == 301 {
637 if got, want := w.HeaderMap.Get("Location"), tt.loc; got != want {
638 t.Errorf("#%d: Location = %q; want = %q", i, got, want)
639 }
640 } else {
641 if got, want := w.HeaderMap.Get("Result"), tt.want; got != want {
642 t.Errorf("#%d: Result = %q; want = %q", i, got, want)
643 }
644 }
645 }
646 }
647
648
649
650
651 func TestMuxNoSlashRedirectWithTrailingSlash(t *testing.T) {
652 mux := NewServeMux()
653 mux.HandleFunc("/{x}/", func(w ResponseWriter, r *Request) {
654 fmt.Fprintln(w, "ok")
655 })
656 w := httptest.NewRecorder()
657 req, _ := NewRequest("GET", "/", nil)
658 mux.ServeHTTP(w, req)
659 if g, w := w.Code, 404; g != w {
660 t.Errorf("got %d, want %d", g, w)
661 }
662 }
663
664
665
666
667 func TestMuxNoSlash405WithTrailingSlash(t *testing.T) {
668 mux := NewServeMux()
669 mux.HandleFunc("GET /{x}/", func(w ResponseWriter, r *Request) {
670 fmt.Fprintln(w, "ok")
671 })
672 w := httptest.NewRecorder()
673 req, _ := NewRequest("GET", "/", nil)
674 mux.ServeHTTP(w, req)
675 if g, w := w.Code, 404; g != w {
676 t.Errorf("got %d, want %d", g, w)
677 }
678 }
679
680 func TestShouldRedirectConcurrency(t *testing.T) { run(t, testShouldRedirectConcurrency) }
681 func testShouldRedirectConcurrency(t *testing.T, mode testMode) {
682 mux := NewServeMux()
683 newClientServerTest(t, mode, mux)
684 mux.HandleFunc("/", func(w ResponseWriter, r *Request) {})
685 }
686
687 func BenchmarkServeMux(b *testing.B) { benchmarkServeMux(b, true) }
688 func BenchmarkServeMux_SkipServe(b *testing.B) { benchmarkServeMux(b, false) }
689 func benchmarkServeMux(b *testing.B, runHandler bool) {
690 type test struct {
691 path string
692 code int
693 req *Request
694 }
695
696
697 var tests []test
698 endpoints := []string{"search", "dir", "file", "change", "count", "s"}
699 for _, e := range endpoints {
700 for i := 200; i < 230; i++ {
701 p := fmt.Sprintf("/%s/%d/", e, i)
702 tests = append(tests, test{
703 path: p,
704 code: i,
705 req: &Request{Method: "GET", Host: "localhost", URL: &url.URL{Path: p}},
706 })
707 }
708 }
709 mux := NewServeMux()
710 for _, tt := range tests {
711 mux.Handle(tt.path, serve(tt.code))
712 }
713
714 rw := httptest.NewRecorder()
715 b.ReportAllocs()
716 b.ResetTimer()
717 for i := 0; i < b.N; i++ {
718 for _, tt := range tests {
719 *rw = httptest.ResponseRecorder{}
720 h, pattern := mux.Handler(tt.req)
721 if runHandler {
722 h.ServeHTTP(rw, tt.req)
723 if pattern != tt.path || rw.Code != tt.code {
724 b.Fatalf("got %d, %q, want %d, %q", rw.Code, pattern, tt.code, tt.path)
725 }
726 }
727 }
728 }
729 }
730
731 func TestServerTimeouts(t *testing.T) { run(t, testServerTimeouts, []testMode{http1Mode}) }
732 func testServerTimeouts(t *testing.T, mode testMode) {
733 runTimeSensitiveTest(t, []time.Duration{
734 10 * time.Millisecond,
735 50 * time.Millisecond,
736 100 * time.Millisecond,
737 500 * time.Millisecond,
738 1 * time.Second,
739 }, func(t *testing.T, timeout time.Duration) error {
740 return testServerTimeoutsWithTimeout(t, timeout, mode)
741 })
742 }
743
744 func testServerTimeoutsWithTimeout(t *testing.T, timeout time.Duration, mode testMode) error {
745 var reqNum atomic.Int32
746 cst := newClientServerTest(t, mode, HandlerFunc(func(res ResponseWriter, req *Request) {
747 fmt.Fprintf(res, "req=%d", reqNum.Add(1))
748 }), func(ts *httptest.Server) {
749 ts.Config.ReadTimeout = timeout
750 ts.Config.WriteTimeout = timeout
751 })
752 defer cst.close()
753 ts := cst.ts
754
755
756 c := ts.Client()
757 r, err := c.Get(ts.URL)
758 if err != nil {
759 return fmt.Errorf("http Get #1: %v", err)
760 }
761 got, err := io.ReadAll(r.Body)
762 expected := "req=1"
763 if string(got) != expected || err != nil {
764 return fmt.Errorf("Unexpected response for request #1; got %q ,%v; expected %q, nil",
765 string(got), err, expected)
766 }
767
768
769 t1 := time.Now()
770 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
771 if err != nil {
772 return fmt.Errorf("Dial: %v", err)
773 }
774 buf := make([]byte, 1)
775 n, err := conn.Read(buf)
776 conn.Close()
777 latency := time.Since(t1)
778 if n != 0 || err != io.EOF {
779 return fmt.Errorf("Read = %v, %v, wanted %v, %v", n, err, 0, io.EOF)
780 }
781 minLatency := timeout / 5 * 4
782 if latency < minLatency {
783 return fmt.Errorf("got EOF after %s, want >= %s", latency, minLatency)
784 }
785
786
787
788
789 r, err = c.Get(ts.URL)
790 if err != nil {
791 return fmt.Errorf("http Get #2: %v", err)
792 }
793 got, err = io.ReadAll(r.Body)
794 r.Body.Close()
795 expected = "req=2"
796 if string(got) != expected || err != nil {
797 return fmt.Errorf("Get #2 got %q, %v, want %q, nil", string(got), err, expected)
798 }
799
800 if !testing.Short() {
801 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
802 if err != nil {
803 return fmt.Errorf("long Dial: %v", err)
804 }
805 defer conn.Close()
806 go io.Copy(io.Discard, conn)
807 for i := 0; i < 5; i++ {
808 _, err := conn.Write([]byte("GET / HTTP/1.1\r\nHost: foo\r\n\r\n"))
809 if err != nil {
810 return fmt.Errorf("on write %d: %v", i, err)
811 }
812 time.Sleep(timeout / 2)
813 }
814 }
815 return nil
816 }
817
818 func TestServerUnencryptedHTTP2HeaderTimeout(t *testing.T) {
819 for _, test := range []struct {
820 name string
821 f func(*fakeNetConn)
822 }{{
823 name: "client sends nothing",
824 f: func(conn *fakeNetConn) {
825 },
826 }, {
827 name: "client sends slowly",
828 f: func(conn *fakeNetConn) {
829
830 conn.Write([]byte("PRI"))
831 time.Sleep(100 * time.Millisecond)
832 conn.Write([]byte(" * "))
833 time.Sleep(100 * time.Millisecond)
834 conn.Write([]byte("HTT"))
835 time.Sleep(100 * time.Millisecond)
836 },
837 }, {
838 name: "header read expires",
839 f: func(conn *fakeNetConn) {
840
841
842 time.Sleep(100 * time.Millisecond)
843 conn.Write([]byte("GET / HTTP/1.1\r\nHost: example.tld\r\n"))
844 },
845 }} {
846 t.Run(test.name, func(t *testing.T) {
847 synctest.Test(t, func(t *testing.T) {
848 listener := fakeNetListen()
849 defer listener.Close()
850
851 srv := &Server{
852 Protocols: new(Protocols),
853 ReadHeaderTimeout: 1 * time.Second,
854 }
855 srv.Protocols.SetHTTP1(true)
856 srv.Protocols.SetUnencryptedHTTP2(true)
857 go srv.Serve(listener)
858
859 conn := listener.connect()
860 go test.f(conn)
861
862 start := time.Now()
863 _, err := io.ReadAll(conn)
864 if err != nil {
865 t.Errorf("ReadAll from server: %v, want EOF", err)
866 }
867 if got, want := time.Since(start), srv.ReadHeaderTimeout; got != want {
868 t.Errorf("connection closed after %v, want %v", got, want)
869 }
870 })
871 })
872 }
873 }
874
875 func TestServerReadTimeout(t *testing.T) { run(t, testServerReadTimeout) }
876 func testServerReadTimeout(t *testing.T, mode testMode) {
877 respBody := "response body"
878 for timeout := 5 * time.Millisecond; ; timeout *= 2 {
879 cst := newClientServerTest(t, mode, HandlerFunc(func(res ResponseWriter, req *Request) {
880 _, err := io.Copy(io.Discard, req.Body)
881 if !errors.Is(err, os.ErrDeadlineExceeded) {
882 t.Errorf("server timed out reading request body: got err %v; want os.ErrDeadlineExceeded", err)
883 }
884 res.Write([]byte(respBody))
885 }), func(ts *httptest.Server) {
886 ts.Config.ReadHeaderTimeout = -1
887 ts.Config.ReadTimeout = timeout
888 t.Logf("Server.Config.ReadTimeout = %v", timeout)
889 })
890
891 var retries atomic.Int32
892 cst.c.Transport.(*Transport).Proxy = func(*Request) (*url.URL, error) {
893 if retries.Add(1) != 1 {
894 return nil, errors.New("too many retries")
895 }
896 return nil, nil
897 }
898
899 pr, pw := io.Pipe()
900 res, err := cst.c.Post(cst.ts.URL, "text/apocryphal", pr)
901 if err != nil {
902 t.Logf("Get error, retrying: %v", err)
903 cst.close()
904 continue
905 }
906 defer res.Body.Close()
907 got, err := io.ReadAll(res.Body)
908 if string(got) != respBody || err != nil {
909 t.Errorf("client read response body: %q, %v; want %q, nil", string(got), err, respBody)
910 }
911 pw.Close()
912 break
913 }
914 }
915
916 func TestServerNoReadTimeout(t *testing.T) { run(t, testServerNoReadTimeout) }
917 func testServerNoReadTimeout(t *testing.T, mode testMode) {
918 reqBody := "Hello, Gophers!"
919 resBody := "Hi, Gophers!"
920 for _, timeout := range []time.Duration{0, -1} {
921 cst := newClientServerTest(t, mode, HandlerFunc(func(res ResponseWriter, req *Request) {
922 ctl := NewResponseController(res)
923 ctl.EnableFullDuplex()
924 res.WriteHeader(StatusOK)
925
926
927 if err := ctl.Flush(); err != nil {
928 t.Errorf("server flush response: %v", err)
929 return
930 }
931 got, err := io.ReadAll(req.Body)
932 if string(got) != reqBody || err != nil {
933 t.Errorf("server read request body: %v; got %q, want %q", err, got, reqBody)
934 }
935 res.Write([]byte(resBody))
936 }), func(ts *httptest.Server) {
937 ts.Config.ReadTimeout = timeout
938 t.Logf("Server.Config.ReadTimeout = %d", timeout)
939 })
940
941 pr, pw := io.Pipe()
942 res, err := cst.c.Post(cst.ts.URL, "text/plain", pr)
943 if err != nil {
944 t.Fatal(err)
945 }
946 defer res.Body.Close()
947
948
949 time.Sleep(10 * time.Millisecond)
950 pw.Write([]byte(reqBody))
951 pw.Close()
952
953 got, err := io.ReadAll(res.Body)
954 if string(got) != resBody || err != nil {
955 t.Errorf("client read response body: %v; got %v, want %q", err, got, resBody)
956 }
957 }
958 }
959
960 func TestServerWriteTimeout(t *testing.T) { run(t, testServerWriteTimeout) }
961 func testServerWriteTimeout(t *testing.T, mode testMode) {
962 for timeout := 5 * time.Millisecond; ; timeout *= 2 {
963 errc := make(chan error, 2)
964 cst := newClientServerTest(t, mode, HandlerFunc(func(res ResponseWriter, req *Request) {
965 errc <- nil
966 _, err := io.Copy(res, neverEnding('a'))
967 errc <- err
968 }), func(ts *httptest.Server) {
969 ts.Config.WriteTimeout = timeout
970 t.Logf("Server.Config.WriteTimeout = %v", timeout)
971 })
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990 var retries atomic.Int32
991 cst.c.Transport.(*Transport).Proxy = func(*Request) (*url.URL, error) {
992 if retries.Add(1) != 1 {
993 return nil, errors.New("too many retries")
994 }
995 return nil, nil
996 }
997
998 res, err := cst.c.Get(cst.ts.URL)
999 if err != nil {
1000
1001 t.Logf("Get error, retrying: %v", err)
1002 cst.close()
1003 continue
1004 }
1005 defer res.Body.Close()
1006 _, err = io.Copy(io.Discard, res.Body)
1007 if err == nil {
1008 t.Errorf("client reading from truncated request body: got nil error, want non-nil")
1009 }
1010 select {
1011 case <-errc:
1012 err = <-errc
1013 if !errors.Is(err, os.ErrDeadlineExceeded) {
1014 t.Errorf("server timed out writing request body: got err %v; want os.ErrDeadlineExceeded", err)
1015 }
1016 return
1017 default:
1018
1019 t.Logf("handler didn't run, retrying")
1020 cst.close()
1021 }
1022 }
1023 }
1024
1025 func TestServerNoWriteTimeout(t *testing.T) { run(t, testServerNoWriteTimeout) }
1026 func testServerNoWriteTimeout(t *testing.T, mode testMode) {
1027 for _, timeout := range []time.Duration{0, -1} {
1028 cst := newClientServerTest(t, mode, HandlerFunc(func(res ResponseWriter, req *Request) {
1029 _, err := io.Copy(res, neverEnding('a'))
1030 t.Logf("server write response: %v", err)
1031 }), func(ts *httptest.Server) {
1032 ts.Config.WriteTimeout = timeout
1033 t.Logf("Server.Config.WriteTimeout = %d", timeout)
1034 })
1035
1036 res, err := cst.c.Get(cst.ts.URL)
1037 if err != nil {
1038 t.Fatal(err)
1039 }
1040 defer res.Body.Close()
1041 n, err := io.CopyN(io.Discard, res.Body, 1<<20)
1042 if n != 1<<20 || err != nil {
1043 t.Errorf("client read response body: %d, %v", n, err)
1044 }
1045
1046
1047 res.Body.Close()
1048 cst.ts.Config.Shutdown(context.Background())
1049 }
1050 }
1051
1052
1053 func TestWriteDeadlineExtendedOnNewRequest(t *testing.T) {
1054 run(t, testWriteDeadlineExtendedOnNewRequest)
1055 }
1056 func testWriteDeadlineExtendedOnNewRequest(t *testing.T, mode testMode) {
1057 if testing.Short() {
1058 t.Skip("skipping in short mode")
1059 }
1060 ts := newClientServerTest(t, mode, HandlerFunc(func(res ResponseWriter, req *Request) {}),
1061 func(ts *httptest.Server) {
1062 ts.Config.WriteTimeout = 250 * time.Millisecond
1063 },
1064 ).ts
1065
1066 c := ts.Client()
1067
1068 for i := 1; i <= 3; i++ {
1069 req, err := NewRequest("GET", ts.URL, nil)
1070 if err != nil {
1071 t.Fatal(err)
1072 }
1073
1074 r, err := c.Do(req)
1075 if err != nil {
1076 t.Fatalf("http2 Get #%d: %v", i, err)
1077 }
1078 r.Body.Close()
1079 time.Sleep(ts.Config.WriteTimeout / 2)
1080 }
1081 }
1082
1083
1084
1085 func tryTimeouts(t *testing.T, testFunc func(timeout time.Duration) error) {
1086 tries := []time.Duration{250 * time.Millisecond, 500 * time.Millisecond, 1 * time.Second}
1087 for i, timeout := range tries {
1088 err := testFunc(timeout)
1089 if err == nil {
1090 return
1091 }
1092 t.Logf("failed at %v: %v", timeout, err)
1093 if i != len(tries)-1 {
1094 t.Logf("retrying at %v ...", tries[i+1])
1095 }
1096 }
1097 t.Fatal("all attempts failed")
1098 }
1099
1100
1101 func TestWriteDeadlineEnforcedPerStream(t *testing.T) {
1102 if testing.Short() {
1103 t.Skip("skipping in short mode")
1104 }
1105 setParallel(t)
1106 run(t, func(t *testing.T, mode testMode) {
1107 tryTimeouts(t, func(timeout time.Duration) error {
1108 return testWriteDeadlineEnforcedPerStream(t, mode, timeout)
1109 })
1110 })
1111 }
1112
1113 func testWriteDeadlineEnforcedPerStream(t *testing.T, mode testMode, timeout time.Duration) error {
1114 firstRequest := make(chan bool, 1)
1115 cst := newClientServerTest(t, mode, HandlerFunc(func(res ResponseWriter, req *Request) {
1116 select {
1117 case firstRequest <- true:
1118
1119 default:
1120
1121 time.Sleep(timeout)
1122 }
1123 }), func(ts *httptest.Server) {
1124 ts.Config.WriteTimeout = timeout / 2
1125 })
1126 defer cst.close()
1127 ts := cst.ts
1128
1129 c := ts.Client()
1130
1131 req, err := NewRequest("GET", ts.URL, nil)
1132 if err != nil {
1133 return fmt.Errorf("NewRequest: %v", err)
1134 }
1135 r, err := c.Do(req)
1136 if err != nil {
1137 return fmt.Errorf("Get #1: %v", err)
1138 }
1139 r.Body.Close()
1140
1141 req, err = NewRequest("GET", ts.URL, nil)
1142 if err != nil {
1143 return fmt.Errorf("NewRequest: %v", err)
1144 }
1145 r, err = c.Do(req)
1146 if err == nil {
1147 r.Body.Close()
1148 return fmt.Errorf("Get #2 expected error, got nil")
1149 }
1150 if mode == http2Mode {
1151 expected := "stream ID 3; INTERNAL_ERROR"
1152 if !strings.Contains(err.Error(), expected) {
1153 return fmt.Errorf("http2 Get #2: expected error to contain %q, got %q", expected, err)
1154 }
1155 }
1156 return nil
1157 }
1158
1159
1160 func TestNoWriteDeadline(t *testing.T) {
1161 if testing.Short() {
1162 t.Skip("skipping in short mode")
1163 }
1164 setParallel(t)
1165 defer afterTest(t)
1166 run(t, func(t *testing.T, mode testMode) {
1167 tryTimeouts(t, func(timeout time.Duration) error {
1168 return testNoWriteDeadline(t, mode, timeout)
1169 })
1170 })
1171 }
1172
1173 func testNoWriteDeadline(t *testing.T, mode testMode, timeout time.Duration) error {
1174 firstRequest := make(chan bool, 1)
1175 cst := newClientServerTest(t, mode, HandlerFunc(func(res ResponseWriter, req *Request) {
1176 select {
1177 case firstRequest <- true:
1178
1179 default:
1180
1181 time.Sleep(timeout)
1182 }
1183 }))
1184 defer cst.close()
1185 ts := cst.ts
1186
1187 c := ts.Client()
1188
1189 for i := 0; i < 2; i++ {
1190 req, err := NewRequest("GET", ts.URL, nil)
1191 if err != nil {
1192 return fmt.Errorf("NewRequest: %v", err)
1193 }
1194 r, err := c.Do(req)
1195 if err != nil {
1196 return fmt.Errorf("Get #%d: %v", i, err)
1197 }
1198 r.Body.Close()
1199 }
1200 return nil
1201 }
1202
1203
1204
1205
1206 func TestOnlyWriteTimeout(t *testing.T) { run(t, testOnlyWriteTimeout, []testMode{http1Mode}) }
1207 func testOnlyWriteTimeout(t *testing.T, mode testMode) {
1208 var (
1209 mu sync.RWMutex
1210 conn net.Conn
1211 )
1212 var afterTimeoutErrc = make(chan error, 1)
1213 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, req *Request) {
1214 buf := make([]byte, 512<<10)
1215 _, err := w.Write(buf)
1216 if err != nil {
1217 t.Errorf("handler Write error: %v", err)
1218 return
1219 }
1220 mu.RLock()
1221 defer mu.RUnlock()
1222 if conn == nil {
1223 t.Error("no established connection found")
1224 return
1225 }
1226 conn.SetWriteDeadline(time.Now().Add(-30 * time.Second))
1227 _, err = w.Write(buf)
1228 afterTimeoutErrc <- err
1229 }), func(ts *httptest.Server) {
1230 ts.Listener = trackLastConnListener{ts.Listener, &mu, &conn}
1231 }).ts
1232
1233 c := ts.Client()
1234
1235 err := func() error {
1236 res, err := c.Get(ts.URL)
1237 if err != nil {
1238 return err
1239 }
1240 _, err = io.Copy(io.Discard, res.Body)
1241 res.Body.Close()
1242 return err
1243 }()
1244 if err == nil {
1245 t.Errorf("expected an error copying body from Get request")
1246 }
1247
1248 if err := <-afterTimeoutErrc; err == nil {
1249 t.Error("expected write error after timeout")
1250 }
1251 }
1252
1253
1254 type trackLastConnListener struct {
1255 net.Listener
1256
1257 mu *sync.RWMutex
1258 last *net.Conn
1259 }
1260
1261 func (l trackLastConnListener) Accept() (c net.Conn, err error) {
1262 c, err = l.Listener.Accept()
1263 if err == nil {
1264 l.mu.Lock()
1265 *l.last = c
1266 l.mu.Unlock()
1267 }
1268 return
1269 }
1270
1271
1272 func TestIdentityResponse(t *testing.T) { run(t, testIdentityResponse) }
1273 func testIdentityResponse(t *testing.T, mode testMode) {
1274 if mode == http2Mode {
1275 t.Skip("https://go.dev/issue/56019")
1276 }
1277
1278 handler := HandlerFunc(func(rw ResponseWriter, req *Request) {
1279 rw.Header().Set("Content-Length", "3")
1280 rw.Header().Set("Transfer-Encoding", req.FormValue("te"))
1281 switch {
1282 case req.FormValue("overwrite") == "1":
1283 _, err := rw.Write([]byte("foo TOO LONG"))
1284 if err != ErrContentLength {
1285 t.Errorf("expected ErrContentLength; got %v", err)
1286 }
1287 case req.FormValue("underwrite") == "1":
1288 rw.Header().Set("Content-Length", "500")
1289 rw.Write([]byte("too short"))
1290 default:
1291 rw.Write([]byte("foo"))
1292 }
1293 })
1294
1295 ts := newClientServerTest(t, mode, handler).ts
1296 c := ts.Client()
1297
1298
1299
1300
1301
1302 for _, te := range []string{"", "identity"} {
1303 url := ts.URL + "/?te=" + te
1304 res, err := c.Get(url)
1305 if err != nil {
1306 t.Fatalf("error with Get of %s: %v", url, err)
1307 }
1308 if cl, expected := res.ContentLength, int64(3); cl != expected {
1309 t.Errorf("for %s expected res.ContentLength of %d; got %d", url, expected, cl)
1310 }
1311 if cl, expected := res.Header.Get("Content-Length"), "3"; cl != expected {
1312 t.Errorf("for %s expected Content-Length header of %q; got %q", url, expected, cl)
1313 }
1314 if tl, expected := len(res.TransferEncoding), 0; tl != expected {
1315 t.Errorf("for %s expected len(res.TransferEncoding) of %d; got %d (%v)",
1316 url, expected, tl, res.TransferEncoding)
1317 }
1318 res.Body.Close()
1319 }
1320
1321
1322 url := ts.URL + "/?overwrite=1"
1323 res, err := c.Get(url)
1324 if err != nil {
1325 t.Fatalf("error with Get of %s: %v", url, err)
1326 }
1327 res.Body.Close()
1328
1329 if mode != http1Mode {
1330 return
1331 }
1332
1333
1334
1335 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
1336 if err != nil {
1337 t.Fatalf("error dialing: %v", err)
1338 }
1339 _, err = conn.Write([]byte("GET /?underwrite=1 HTTP/1.1\r\nHost: foo\r\n\r\n"))
1340 if err != nil {
1341 t.Fatalf("error writing: %v", err)
1342 }
1343
1344
1345 got, _ := io.ReadAll(conn)
1346 expectedSuffix := "\r\n\r\ntoo short"
1347 if !strings.HasSuffix(string(got), expectedSuffix) {
1348 t.Errorf("Expected output to end with %q; got response body %q",
1349 expectedSuffix, string(got))
1350 }
1351 }
1352
1353 func testTCPConnectionCloses(t *testing.T, req string, h Handler) {
1354 setParallel(t)
1355 s := newClientServerTest(t, http1Mode, h).ts
1356
1357 conn, err := net.Dial("tcp", s.Listener.Addr().String())
1358 if err != nil {
1359 t.Fatal("dial error:", err)
1360 }
1361 defer conn.Close()
1362
1363 _, err = fmt.Fprint(conn, req)
1364 if err != nil {
1365 t.Fatal("print error:", err)
1366 }
1367
1368 r := bufio.NewReader(conn)
1369 res, err := ReadResponse(r, &Request{Method: "GET"})
1370 if err != nil {
1371 t.Fatal("ReadResponse error:", err)
1372 }
1373
1374 _, err = io.ReadAll(r)
1375 if err != nil {
1376 t.Fatal("read error:", err)
1377 }
1378
1379 if !res.Close {
1380 t.Errorf("Response.Close = false; want true")
1381 }
1382 }
1383
1384 func testTCPConnectionStaysOpen(t *testing.T, req string, handler Handler) {
1385 setParallel(t)
1386 ts := newClientServerTest(t, http1Mode, handler).ts
1387 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
1388 if err != nil {
1389 t.Fatal(err)
1390 }
1391 defer conn.Close()
1392 br := bufio.NewReader(conn)
1393 for i := 0; i < 2; i++ {
1394 if _, err := io.WriteString(conn, req); err != nil {
1395 t.Fatal(err)
1396 }
1397 res, err := ReadResponse(br, nil)
1398 if err != nil {
1399 t.Fatalf("res %d: %v", i+1, err)
1400 }
1401 if _, err := io.Copy(io.Discard, res.Body); err != nil {
1402 t.Fatalf("res %d body copy: %v", i+1, err)
1403 }
1404 res.Body.Close()
1405 }
1406 }
1407
1408
1409 func TestServeHTTP10Close(t *testing.T) {
1410 testTCPConnectionCloses(t, "GET / HTTP/1.0\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
1411 ServeFile(w, r, "testdata/file")
1412 }))
1413 }
1414
1415
1416 func TestClientCanClose(t *testing.T) {
1417 testTCPConnectionCloses(t, "GET / HTTP/1.1\r\nHost: foo\r\nConnection: close\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
1418
1419 }))
1420 }
1421
1422
1423
1424 func TestHandlersCanSetConnectionClose11(t *testing.T) {
1425 testTCPConnectionCloses(t, "GET / HTTP/1.1\r\nHost: foo\r\n\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
1426 w.Header().Set("Connection", "close")
1427 }))
1428 }
1429
1430 func TestHandlersCanSetConnectionClose10(t *testing.T) {
1431 testTCPConnectionCloses(t, "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
1432 w.Header().Set("Connection", "close")
1433 }))
1434 }
1435
1436 func TestHTTP2UpgradeClosesConnection(t *testing.T) {
1437 testTCPConnectionCloses(t, "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
1438
1439
1440 }))
1441 }
1442
1443 func send204(w ResponseWriter, r *Request) { w.WriteHeader(204) }
1444 func send304(w ResponseWriter, r *Request) { w.WriteHeader(304) }
1445
1446
1447 func TestHTTP10KeepAlive204Response(t *testing.T) {
1448 testTCPConnectionStaysOpen(t, "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n", HandlerFunc(send204))
1449 }
1450
1451 func TestHTTP11KeepAlive204Response(t *testing.T) {
1452 testTCPConnectionStaysOpen(t, "GET / HTTP/1.1\r\nHost: foo\r\n\r\n", HandlerFunc(send204))
1453 }
1454
1455 func TestHTTP10KeepAlive304Response(t *testing.T) {
1456 testTCPConnectionStaysOpen(t,
1457 "GET / HTTP/1.0\r\nConnection: keep-alive\r\nIf-Modified-Since: Mon, 02 Jan 2006 15:04:05 GMT\r\n\r\n",
1458 HandlerFunc(send304))
1459 }
1460
1461
1462 func TestKeepAliveFinalChunkWithEOF(t *testing.T) { run(t, testKeepAliveFinalChunkWithEOF) }
1463 func testKeepAliveFinalChunkWithEOF(t *testing.T, mode testMode) {
1464 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
1465 w.(Flusher).Flush()
1466 w.Write([]byte("{\"Addr\": \"" + r.RemoteAddr + "\"}"))
1467 }))
1468 type data struct {
1469 Addr string
1470 }
1471 var addrs [2]data
1472 for i := range addrs {
1473 res, err := cst.c.Get(cst.ts.URL)
1474 if err != nil {
1475 t.Fatal(err)
1476 }
1477 if err := json.NewDecoder(res.Body).Decode(&addrs[i]); err != nil {
1478 t.Fatal(err)
1479 }
1480 if addrs[i].Addr == "" {
1481 t.Fatal("no address")
1482 }
1483 res.Body.Close()
1484 }
1485 if addrs[0] != addrs[1] {
1486 t.Fatalf("connection not reused")
1487 }
1488 }
1489
1490 func TestSetsRemoteAddr(t *testing.T) { run(t, testSetsRemoteAddr) }
1491 func testSetsRemoteAddr(t *testing.T, mode testMode) {
1492 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
1493 fmt.Fprintf(w, "%s", r.RemoteAddr)
1494 }))
1495
1496 res, err := cst.c.Get(cst.ts.URL)
1497 if err != nil {
1498 t.Fatalf("Get error: %v", err)
1499 }
1500 body, err := io.ReadAll(res.Body)
1501 if err != nil {
1502 t.Fatalf("ReadAll error: %v", err)
1503 }
1504 ip := string(body)
1505 if !strings.HasPrefix(ip, "127.0.0.1:") && !strings.HasPrefix(ip, "[::1]:") {
1506 t.Fatalf("Expected local addr; got %q", ip)
1507 }
1508 }
1509
1510 type blockingRemoteAddrListener struct {
1511 net.Listener
1512 conns chan<- net.Conn
1513 }
1514
1515 func (l *blockingRemoteAddrListener) Accept() (net.Conn, error) {
1516 c, err := l.Listener.Accept()
1517 if err != nil {
1518 return nil, err
1519 }
1520 brac := &blockingRemoteAddrConn{
1521 Conn: c,
1522 addrs: make(chan net.Addr, 1),
1523 }
1524 l.conns <- brac
1525 return brac, nil
1526 }
1527
1528 type blockingRemoteAddrConn struct {
1529 net.Conn
1530 addrs chan net.Addr
1531 }
1532
1533 func (c *blockingRemoteAddrConn) RemoteAddr() net.Addr {
1534 return <-c.addrs
1535 }
1536
1537
1538 func TestServerAllowsBlockingRemoteAddr(t *testing.T) {
1539 run(t, testServerAllowsBlockingRemoteAddr, []testMode{http1Mode})
1540 }
1541 func testServerAllowsBlockingRemoteAddr(t *testing.T, mode testMode) {
1542 conns := make(chan net.Conn)
1543 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
1544 fmt.Fprintf(w, "RA:%s", r.RemoteAddr)
1545 }), func(ts *httptest.Server) {
1546 ts.Listener = &blockingRemoteAddrListener{
1547 Listener: ts.Listener,
1548 conns: conns,
1549 }
1550 }).ts
1551
1552 c := ts.Client()
1553
1554 c.Transport.(*Transport).DisableKeepAlives = true
1555
1556 fetch := func(num int, response chan<- string) {
1557 resp, err := c.Get(ts.URL)
1558 if err != nil {
1559 t.Errorf("Request %d: %v", num, err)
1560 response <- ""
1561 return
1562 }
1563 defer resp.Body.Close()
1564 body, err := io.ReadAll(resp.Body)
1565 if err != nil {
1566 t.Errorf("Request %d: %v", num, err)
1567 response <- ""
1568 return
1569 }
1570 response <- string(body)
1571 }
1572
1573
1574 response1c := make(chan string, 1)
1575 go fetch(1, response1c)
1576
1577
1578 conn1 := <-conns
1579
1580
1581 response2c := make(chan string, 1)
1582 go fetch(2, response2c)
1583 conn2 := <-conns
1584
1585
1586 conn2.(*blockingRemoteAddrConn).addrs <- &net.TCPAddr{
1587 IP: net.ParseIP("12.12.12.12"), Port: 12}
1588
1589
1590 response2 := <-response2c
1591 if g, e := response2, "RA:12.12.12.12:12"; g != e {
1592 t.Fatalf("response 2 addr = %q; want %q", g, e)
1593 }
1594
1595
1596 conn1.(*blockingRemoteAddrConn).addrs <- &net.TCPAddr{
1597 IP: net.ParseIP("21.21.21.21"), Port: 21}
1598
1599
1600 response1 := <-response1c
1601 if g, e := response1, "RA:21.21.21.21:21"; g != e {
1602 t.Fatalf("response 1 addr = %q; want %q", g, e)
1603 }
1604 }
1605
1606
1607
1608 func TestHeadResponses(t *testing.T) { run(t, testHeadResponses) }
1609 func testHeadResponses(t *testing.T, mode testMode) {
1610 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
1611 _, err := w.Write([]byte("<html>"))
1612 if err != nil {
1613 t.Errorf("ResponseWriter.Write: %v", err)
1614 }
1615
1616
1617 _, err = io.Copy(w, struct{ io.Reader }{strings.NewReader("789a")})
1618 if err != nil {
1619 t.Errorf("Copy(ResponseWriter, ...): %v", err)
1620 }
1621 }))
1622 res, err := cst.c.Head(cst.ts.URL)
1623 if err != nil {
1624 t.Error(err)
1625 }
1626 if len(res.TransferEncoding) > 0 {
1627 t.Errorf("expected no TransferEncoding; got %v", res.TransferEncoding)
1628 }
1629 if ct := res.Header.Get("Content-Type"); ct != "text/html; charset=utf-8" {
1630 t.Errorf("Content-Type: %q; want text/html; charset=utf-8", ct)
1631 }
1632 if v := res.ContentLength; v != 10 {
1633 t.Errorf("Content-Length: %d; want 10", v)
1634 }
1635 body, err := io.ReadAll(res.Body)
1636 if err != nil {
1637 t.Error(err)
1638 }
1639 if len(body) > 0 {
1640 t.Errorf("got unexpected body %q", string(body))
1641 }
1642 }
1643
1644
1645
1646 func TestHeadReaderFrom(t *testing.T) { run(t, testHeadReaderFrom, []testMode{http1Mode}) }
1647 func testHeadReaderFrom(t *testing.T, mode testMode) {
1648
1649 wantBody := strings.Repeat("a", 4096)
1650 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
1651 w.(io.ReaderFrom).ReadFrom(strings.NewReader(wantBody))
1652 }))
1653 res, err := cst.c.Head(cst.ts.URL)
1654 if err != nil {
1655 t.Fatal(err)
1656 }
1657 res.Body.Close()
1658 res, err = cst.c.Get(cst.ts.URL)
1659 if err != nil {
1660 t.Fatal(err)
1661 }
1662 gotBody, err := io.ReadAll(res.Body)
1663 res.Body.Close()
1664 if err != nil {
1665 t.Fatal(err)
1666 }
1667 if string(gotBody) != wantBody {
1668 t.Errorf("got unexpected body len=%v, want %v", len(gotBody), len(wantBody))
1669 }
1670 }
1671
1672 func TestTLSHandshakeTimeout(t *testing.T) {
1673 run(t, testTLSHandshakeTimeout, []testMode{https1Mode, http2Mode})
1674 }
1675 func testTLSHandshakeTimeout(t *testing.T, mode testMode) {
1676 errLog := new(strings.Builder)
1677 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {}),
1678 func(ts *httptest.Server) {
1679 ts.Config.ReadTimeout = 250 * time.Millisecond
1680 ts.Config.ErrorLog = log.New(errLog, "", 0)
1681 },
1682 )
1683 ts := cst.ts
1684
1685 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
1686 if err != nil {
1687 t.Fatalf("Dial: %v", err)
1688 }
1689 var buf [1]byte
1690 n, err := conn.Read(buf[:])
1691 if err == nil || n != 0 {
1692 t.Errorf("Read = %d, %v; want an error and no bytes", n, err)
1693 }
1694 conn.Close()
1695
1696 cst.close()
1697 if v := errLog.String(); !strings.Contains(v, "timeout") && !strings.Contains(v, "TLS handshake") {
1698 t.Errorf("expected a TLS handshake timeout error; got %q", v)
1699 }
1700 }
1701
1702 func TestTLSServer(t *testing.T) { run(t, testTLSServer, []testMode{https1Mode, http2Mode}) }
1703 func testTLSServer(t *testing.T, mode testMode) {
1704 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
1705 if r.TLS != nil {
1706 w.Header().Set("X-TLS-Set", "true")
1707 if r.TLS.HandshakeComplete {
1708 w.Header().Set("X-TLS-HandshakeComplete", "true")
1709 }
1710 }
1711 }), func(ts *httptest.Server) {
1712 ts.Config.ErrorLog = log.New(io.Discard, "", 0)
1713 }).ts
1714
1715
1716
1717
1718
1719
1720 idleConn, err := net.Dial("tcp", ts.Listener.Addr().String())
1721 if err != nil {
1722 t.Fatalf("Dial: %v", err)
1723 }
1724 defer idleConn.Close()
1725
1726 if !strings.HasPrefix(ts.URL, "https://") {
1727 t.Errorf("expected test TLS server to start with https://, got %q", ts.URL)
1728 return
1729 }
1730 client := ts.Client()
1731 res, err := client.Get(ts.URL)
1732 if err != nil {
1733 t.Error(err)
1734 return
1735 }
1736 if res == nil {
1737 t.Errorf("got nil Response")
1738 return
1739 }
1740 defer res.Body.Close()
1741 if res.Header.Get("X-TLS-Set") != "true" {
1742 t.Errorf("expected X-TLS-Set response header")
1743 return
1744 }
1745 if res.Header.Get("X-TLS-HandshakeComplete") != "true" {
1746 t.Errorf("expected X-TLS-HandshakeComplete header")
1747 }
1748 }
1749
1750 type fakeConnectionStateConn struct {
1751 net.Conn
1752 }
1753
1754 func (fcsc *fakeConnectionStateConn) ConnectionState() tls.ConnectionState {
1755 return tls.ConnectionState{
1756 ServerName: "example.com",
1757 }
1758 }
1759
1760 func TestTLSServerWithoutTLSConn(t *testing.T) {
1761
1762 pr, pw := net.Pipe()
1763 c := make(chan int)
1764 listener := &oneConnListener{&fakeConnectionStateConn{pr}}
1765 server := &Server{
1766 Handler: HandlerFunc(func(writer ResponseWriter, request *Request) {
1767 if request.TLS == nil {
1768 t.Fatal("request.TLS is nil, expected not nil")
1769 }
1770 if request.TLS.ServerName != "example.com" {
1771 t.Fatalf("request.TLS.ServerName is %s, expected %s", request.TLS.ServerName, "example.com")
1772 }
1773 writer.Header().Set("X-TLS-ServerName", "example.com")
1774 }),
1775 }
1776
1777
1778 go func() {
1779 req, _ := NewRequest(MethodGet, "https://example.com", nil)
1780 req.Write(pw)
1781
1782 resp, _ := ReadResponse(bufio.NewReader(pw), req)
1783 if hdr := resp.Header.Get("X-TLS-ServerName"); hdr != "example.com" {
1784 t.Errorf("response header X-TLS-ServerName is %s, expected %s", hdr, "example.com")
1785 }
1786 close(c)
1787 pw.Close()
1788 }()
1789
1790 server.Serve(listener)
1791
1792
1793 <-c
1794 pr.Close()
1795 }
1796
1797 func TestServeTLS(t *testing.T) {
1798 CondSkipHTTP2(t)
1799
1800 defer afterTest(t)
1801 defer SetTestHookServerServe(nil)
1802
1803 cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey)
1804 if err != nil {
1805 t.Fatal(err)
1806 }
1807 tlsConf := &tls.Config{
1808 Certificates: []tls.Certificate{cert},
1809 }
1810
1811 ln := newLocalListener(t)
1812 defer ln.Close()
1813 addr := ln.Addr().String()
1814
1815 serving := make(chan bool, 1)
1816 SetTestHookServerServe(func(s *Server, ln net.Listener) {
1817 serving <- true
1818 })
1819 handler := HandlerFunc(func(w ResponseWriter, r *Request) {})
1820 s := &Server{
1821 Addr: addr,
1822 TLSConfig: tlsConf,
1823 Handler: handler,
1824 }
1825 errc := make(chan error, 1)
1826 go func() { errc <- s.ServeTLS(ln, "", "") }()
1827 select {
1828 case err := <-errc:
1829 t.Fatalf("ServeTLS: %v", err)
1830 case <-serving:
1831 }
1832
1833 c, err := tls.Dial("tcp", ln.Addr().String(), &tls.Config{
1834 InsecureSkipVerify: true,
1835 NextProtos: []string{"h2", "http/1.1"},
1836 })
1837 if err != nil {
1838 t.Fatal(err)
1839 }
1840 defer c.Close()
1841 if got, want := c.ConnectionState().NegotiatedProtocol, "h2"; got != want {
1842 t.Errorf("NegotiatedProtocol = %q; want %q", got, want)
1843 }
1844 if got, want := c.ConnectionState().NegotiatedProtocolIsMutual, true; got != want {
1845 t.Errorf("NegotiatedProtocolIsMutual = %v; want %v", got, want)
1846 }
1847 }
1848
1849
1850 func TestTLSServerRejectHTTPRequests(t *testing.T) {
1851 run(t, testTLSServerRejectHTTPRequests, []testMode{https1Mode, http2Mode})
1852 }
1853 func testTLSServerRejectHTTPRequests(t *testing.T, mode testMode) {
1854 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
1855 t.Error("unexpected HTTPS request")
1856 }), func(ts *httptest.Server) {
1857 var errBuf bytes.Buffer
1858 ts.Config.ErrorLog = log.New(&errBuf, "", 0)
1859 }).ts
1860 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
1861 if err != nil {
1862 t.Fatal(err)
1863 }
1864 defer conn.Close()
1865 io.WriteString(conn, "GET / HTTP/1.1\r\nHost: foo\r\n\r\n")
1866 slurp, err := io.ReadAll(conn)
1867 if err != nil {
1868 t.Fatal(err)
1869 }
1870 const wantPrefix = "HTTP/1.0 400 Bad Request\r\n"
1871 if !strings.HasPrefix(string(slurp), wantPrefix) {
1872 t.Errorf("response = %q; wanted prefix %q", slurp, wantPrefix)
1873 }
1874 }
1875
1876
1877 func TestAutomaticHTTP2_Serve_NoTLSConfig(t *testing.T) {
1878 testAutomaticHTTP2_Serve(t, nil, true)
1879 }
1880
1881 func TestAutomaticHTTP2_Serve_NonH2TLSConfig(t *testing.T) {
1882 testAutomaticHTTP2_Serve(t, &tls.Config{}, false)
1883 }
1884
1885 func TestAutomaticHTTP2_Serve_H2TLSConfig(t *testing.T) {
1886 testAutomaticHTTP2_Serve(t, &tls.Config{NextProtos: []string{"h2"}}, true)
1887 }
1888
1889 func testAutomaticHTTP2_Serve(t *testing.T, tlsConf *tls.Config, wantH2 bool) {
1890 setParallel(t)
1891 defer afterTest(t)
1892 ln := newLocalListener(t)
1893 ln.Close()
1894 var s Server
1895 s.TLSConfig = tlsConf
1896 if err := s.Serve(ln); err == nil {
1897 t.Fatal("expected an error")
1898 }
1899 gotH2 := s.TLSNextProto["h2"] != nil
1900 if gotH2 != wantH2 {
1901 t.Errorf("http2 configured = %v; want %v", gotH2, wantH2)
1902 }
1903 }
1904
1905 func TestAutomaticHTTP2_Serve_WithTLSConfig(t *testing.T) {
1906 setParallel(t)
1907 defer afterTest(t)
1908 ln := newLocalListener(t)
1909 ln.Close()
1910 var s Server
1911
1912
1913 s.TLSConfig = &tls.Config{
1914 NextProtos: []string{"h2"},
1915 }
1916 if err := s.Serve(ln); err == nil {
1917 t.Fatal("expected an error")
1918 }
1919 on := s.TLSNextProto["h2"] != nil
1920 if !on {
1921 t.Errorf("http2 wasn't automatically enabled")
1922 }
1923 }
1924
1925 func TestAutomaticHTTP2_ListenAndServe(t *testing.T) {
1926 cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey)
1927 if err != nil {
1928 t.Fatal(err)
1929 }
1930 testAutomaticHTTP2_ListenAndServe(t, &tls.Config{
1931 Certificates: []tls.Certificate{cert},
1932 })
1933 }
1934
1935 func TestAutomaticHTTP2_ListenAndServe_GetCertificate(t *testing.T) {
1936 cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey)
1937 if err != nil {
1938 t.Fatal(err)
1939 }
1940 testAutomaticHTTP2_ListenAndServe(t, &tls.Config{
1941 GetCertificate: func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
1942 return &cert, nil
1943 },
1944 })
1945 }
1946
1947 func TestAutomaticHTTP2_ListenAndServe_GetConfigForClient(t *testing.T) {
1948 cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey)
1949 if err != nil {
1950 t.Fatal(err)
1951 }
1952 conf := &tls.Config{
1953
1954
1955 NextProtos: []string{"h2"},
1956 Certificates: []tls.Certificate{cert},
1957 }
1958 testAutomaticHTTP2_ListenAndServe(t, &tls.Config{
1959 GetConfigForClient: func(clientHello *tls.ClientHelloInfo) (*tls.Config, error) {
1960 return conf, nil
1961 },
1962 })
1963 }
1964
1965 func testAutomaticHTTP2_ListenAndServe(t *testing.T, tlsConf *tls.Config) {
1966 CondSkipHTTP2(t)
1967
1968 defer afterTest(t)
1969 defer SetTestHookServerServe(nil)
1970 var ok bool
1971 var s *Server
1972 const maxTries = 5
1973 var ln net.Listener
1974 Try:
1975 for try := 0; try < maxTries; try++ {
1976 ln = newLocalListener(t)
1977 addr := ln.Addr().String()
1978 ln.Close()
1979 t.Logf("Got %v", addr)
1980 lnc := make(chan net.Listener, 1)
1981 SetTestHookServerServe(func(s *Server, ln net.Listener) {
1982 lnc <- ln
1983 })
1984 s = &Server{
1985 Addr: addr,
1986 TLSConfig: tlsConf,
1987 }
1988 errc := make(chan error, 1)
1989 go func() { errc <- s.ListenAndServeTLS("", "") }()
1990 select {
1991 case err := <-errc:
1992 t.Logf("On try #%v: %v", try+1, err)
1993 continue
1994 case ln = <-lnc:
1995 ok = true
1996 t.Logf("Listening on %v", ln.Addr().String())
1997 break Try
1998 }
1999 }
2000 if !ok {
2001 t.Fatalf("Failed to start up after %d tries", maxTries)
2002 }
2003 defer ln.Close()
2004 c, err := tls.Dial("tcp", ln.Addr().String(), &tls.Config{
2005 InsecureSkipVerify: true,
2006 NextProtos: []string{"h2", "http/1.1"},
2007 })
2008 if err != nil {
2009 t.Fatal(err)
2010 }
2011 defer c.Close()
2012 if got, want := c.ConnectionState().NegotiatedProtocol, "h2"; got != want {
2013 t.Errorf("NegotiatedProtocol = %q; want %q", got, want)
2014 }
2015 if got, want := c.ConnectionState().NegotiatedProtocolIsMutual, true; got != want {
2016 t.Errorf("NegotiatedProtocolIsMutual = %v; want %v", got, want)
2017 }
2018 }
2019
2020 type serverExpectTest struct {
2021 contentLength int
2022 chunked bool
2023 expectation string
2024 readBody bool
2025 expectedResponse string
2026 }
2027
2028 func expectTest(contentLength int, expectation string, readBody bool, expectedResponse string) serverExpectTest {
2029 return serverExpectTest{
2030 contentLength: contentLength,
2031 expectation: expectation,
2032 readBody: readBody,
2033 expectedResponse: expectedResponse,
2034 }
2035 }
2036
2037 var serverExpectTests = []serverExpectTest{
2038
2039 expectTest(100, "100-continue", true, "100 Continue"),
2040 expectTest(100, "100-cOntInUE", true, "100 Continue"),
2041
2042
2043 expectTest(100, "", true, "200 OK"),
2044
2045
2046
2047 expectTest(100, "100-continue", false, "401 Unauthorized"),
2048
2049 expectTest(100, "", false, "401 Unauthorized"),
2050
2051
2052 expectTest(0, "a-pony", false, "417 Expectation Failed"),
2053
2054
2055 expectTest(0, "100-continue", true, "200 OK"),
2056
2057 expectTest(0, "100-continue", false, "401 Unauthorized"),
2058
2059 {
2060 expectation: "100-continue",
2061 readBody: true,
2062 chunked: true,
2063 expectedResponse: "100 Continue",
2064 },
2065 }
2066
2067
2068
2069 func TestServerExpect(t *testing.T) { run(t, testServerExpect, []testMode{http1Mode}) }
2070 func testServerExpect(t *testing.T, mode testMode) {
2071 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
2072
2073
2074
2075 if strings.Contains(r.URL.RawQuery, "readbody=true") {
2076 io.ReadAll(r.Body)
2077 w.Write([]byte("Hi"))
2078 } else {
2079 w.WriteHeader(StatusUnauthorized)
2080 }
2081 })).ts
2082
2083 runTest := func(test serverExpectTest) {
2084 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
2085 if err != nil {
2086 t.Fatalf("Dial: %v", err)
2087 }
2088 defer conn.Close()
2089
2090
2091
2092 writeBody := test.contentLength != 0 && strings.ToLower(test.expectation) != "100-continue"
2093
2094 wg := sync.WaitGroup{}
2095 wg.Add(1)
2096 defer wg.Wait()
2097
2098 go func() {
2099 defer wg.Done()
2100
2101 contentLen := fmt.Sprintf("Content-Length: %d", test.contentLength)
2102 if test.chunked {
2103 contentLen = "Transfer-Encoding: chunked"
2104 }
2105 _, err := fmt.Fprintf(conn, "POST /?readbody=%v HTTP/1.1\r\n"+
2106 "Connection: close\r\n"+
2107 "%s\r\n"+
2108 "Expect: %s\r\nHost: foo\r\n\r\n",
2109 test.readBody, contentLen, test.expectation)
2110 if err != nil {
2111 t.Errorf("On test %#v, error writing request headers: %v", test, err)
2112 return
2113 }
2114 if writeBody {
2115 var targ io.WriteCloser = struct {
2116 io.Writer
2117 io.Closer
2118 }{
2119 conn,
2120 io.NopCloser(nil),
2121 }
2122 if test.chunked {
2123 targ = httputil.NewChunkedWriter(conn)
2124 }
2125 body := strings.Repeat("A", test.contentLength)
2126 _, err = fmt.Fprint(targ, body)
2127 if err == nil {
2128 err = targ.Close()
2129 }
2130 if err != nil {
2131 if !test.readBody {
2132
2133
2134 t.Logf("On test %#v, acceptable error writing request body: %v", test, err)
2135 return
2136 }
2137 t.Errorf("On test %#v, error writing request body: %v", test, err)
2138 }
2139 }
2140 }()
2141 bufr := bufio.NewReader(conn)
2142 line, err := bufr.ReadString('\n')
2143 if err != nil {
2144 if writeBody && !test.readBody {
2145
2146
2147
2148
2149
2150 t.Logf("On test %#v, acceptable error from ReadString: %v", test, err)
2151 return
2152 }
2153 t.Fatalf("On test %#v, ReadString: %v", test, err)
2154 }
2155 if !strings.Contains(line, test.expectedResponse) {
2156 t.Errorf("On test %#v, got first line = %q; want %q", test, line, test.expectedResponse)
2157 }
2158 }
2159
2160 for _, test := range serverExpectTests {
2161 runTest(test)
2162 }
2163 }
2164
2165
2166
2167 func TestServerUnreadRequestBodyLittle(t *testing.T) {
2168 setParallel(t)
2169 defer afterTest(t)
2170 conn := new(testConn)
2171 body := strings.Repeat("x", 100<<10)
2172 conn.readBuf.Write([]byte(fmt.Sprintf(
2173 "POST / HTTP/1.1\r\n"+
2174 "Host: test\r\n"+
2175 "Content-Length: %d\r\n"+
2176 "\r\n", len(body))))
2177 conn.readBuf.Write([]byte(body))
2178
2179 done := make(chan bool)
2180
2181 readBufLen := func() int {
2182 conn.readMu.Lock()
2183 defer conn.readMu.Unlock()
2184 return conn.readBuf.Len()
2185 }
2186
2187 ls := &oneConnListener{conn}
2188 go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
2189 defer close(done)
2190 if bufLen := readBufLen(); bufLen < len(body)/2 {
2191 t.Errorf("on request, read buffer length is %d; expected about 100 KB", bufLen)
2192 }
2193 rw.WriteHeader(200)
2194 rw.(Flusher).Flush()
2195 if g, e := readBufLen(), 0; g != e {
2196 t.Errorf("after WriteHeader, read buffer length is %d; want %d", g, e)
2197 }
2198 if c := rw.Header().Get("Connection"); c != "" {
2199 t.Errorf(`Connection header = %q; want ""`, c)
2200 }
2201 }))
2202 <-done
2203 }
2204
2205
2206
2207
2208 func TestServerUnreadRequestBodyLarge(t *testing.T) {
2209 setParallel(t)
2210 if testing.Short() && testenv.Builder() == "" {
2211 t.Log("skipping in short mode")
2212 }
2213 conn := new(testConn)
2214 body := strings.Repeat("x", 1<<20)
2215 conn.readBuf.Write([]byte(fmt.Sprintf(
2216 "POST / HTTP/1.1\r\n"+
2217 "Host: test\r\n"+
2218 "Content-Length: %d\r\n"+
2219 "\r\n", len(body))))
2220 conn.readBuf.Write([]byte(body))
2221 conn.closec = make(chan bool, 1)
2222
2223 ls := &oneConnListener{conn}
2224 go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
2225 if conn.readBuf.Len() < len(body)/2 {
2226 t.Errorf("on request, read buffer length is %d; expected about 1MB", conn.readBuf.Len())
2227 }
2228 rw.WriteHeader(200)
2229 rw.(Flusher).Flush()
2230 if conn.readBuf.Len() < len(body)/2 {
2231 t.Errorf("post-WriteHeader, read buffer length is %d; expected about 1MB", conn.readBuf.Len())
2232 }
2233 }))
2234 <-conn.closec
2235
2236 if res := conn.writeBuf.String(); !strings.Contains(res, "Connection: close") {
2237 t.Errorf("Expected a Connection: close header; got response: %s", res)
2238 }
2239 }
2240
2241 type handlerBodyCloseTest struct {
2242 bodySize int
2243 bodyChunked bool
2244 reqConnClose bool
2245
2246 wantEOFSearch bool
2247 wantNextReq bool
2248 }
2249
2250 func (t handlerBodyCloseTest) connectionHeader() string {
2251 if t.reqConnClose {
2252 return "Connection: close\r\n"
2253 }
2254 return ""
2255 }
2256
2257 var handlerBodyCloseTests = [...]handlerBodyCloseTest{
2258
2259
2260 0: {
2261 bodySize: 20 << 10,
2262 bodyChunked: false,
2263 reqConnClose: false,
2264 wantEOFSearch: true,
2265 wantNextReq: true,
2266 },
2267
2268
2269
2270 1: {
2271 bodySize: 20 << 10,
2272 bodyChunked: true,
2273 reqConnClose: false,
2274 wantEOFSearch: true,
2275 wantNextReq: true,
2276 },
2277
2278
2279
2280
2281 2: {
2282 bodySize: 20 << 10,
2283 bodyChunked: false,
2284 reqConnClose: true,
2285 wantEOFSearch: false,
2286 wantNextReq: false,
2287 },
2288
2289
2290
2291
2292
2293
2294 3: {
2295 bodySize: 20 << 10,
2296 bodyChunked: true,
2297 reqConnClose: true,
2298 wantEOFSearch: true,
2299 wantNextReq: false,
2300 },
2301
2302
2303 4: {
2304 bodySize: 1 << 20,
2305 bodyChunked: false,
2306 reqConnClose: false,
2307 wantEOFSearch: false,
2308 wantNextReq: false,
2309 },
2310
2311
2312 5: {
2313 bodySize: 1 << 20,
2314 bodyChunked: true,
2315 reqConnClose: false,
2316 wantEOFSearch: true,
2317 wantNextReq: false,
2318 },
2319
2320
2321
2322
2323 6: {
2324 bodySize: 1 << 20,
2325 bodyChunked: true,
2326 reqConnClose: true,
2327 wantEOFSearch: true,
2328 wantNextReq: false,
2329 },
2330
2331
2332
2333 7: {
2334 bodySize: 1 << 20,
2335 bodyChunked: false,
2336 reqConnClose: true,
2337 wantEOFSearch: false,
2338 wantNextReq: false,
2339 },
2340 }
2341
2342 func TestHandlerBodyClose(t *testing.T) {
2343 setParallel(t)
2344 if testing.Short() && testenv.Builder() == "" {
2345 t.Skip("skipping in -short mode")
2346 }
2347 for i, tt := range handlerBodyCloseTests {
2348 testHandlerBodyClose(t, i, tt)
2349 }
2350 }
2351
2352 func testHandlerBodyClose(t *testing.T, i int, tt handlerBodyCloseTest) {
2353 conn := new(testConn)
2354 body := strings.Repeat("x", tt.bodySize)
2355 if tt.bodyChunked {
2356 conn.readBuf.WriteString("POST / HTTP/1.1\r\n" +
2357 "Host: test\r\n" +
2358 tt.connectionHeader() +
2359 "Transfer-Encoding: chunked\r\n" +
2360 "\r\n")
2361 cw := internal.NewChunkedWriter(&conn.readBuf)
2362 io.WriteString(cw, body)
2363 cw.Close()
2364 conn.readBuf.WriteString("\r\n")
2365 } else {
2366 conn.readBuf.Write([]byte(fmt.Sprintf(
2367 "POST / HTTP/1.1\r\n"+
2368 "Host: test\r\n"+
2369 tt.connectionHeader()+
2370 "Content-Length: %d\r\n"+
2371 "\r\n", len(body))))
2372 conn.readBuf.Write([]byte(body))
2373 }
2374 if !tt.reqConnClose {
2375 conn.readBuf.WriteString("GET / HTTP/1.1\r\nHost: test\r\n\r\n")
2376 }
2377 conn.closec = make(chan bool, 1)
2378
2379 readBufLen := func() int {
2380 conn.readMu.Lock()
2381 defer conn.readMu.Unlock()
2382 return conn.readBuf.Len()
2383 }
2384
2385 ls := &oneConnListener{conn}
2386 var numReqs int
2387 var size0, size1 int
2388 go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
2389 numReqs++
2390 if numReqs == 1 {
2391 size0 = readBufLen()
2392 req.Body.Close()
2393 size1 = readBufLen()
2394 }
2395 }))
2396 <-conn.closec
2397 if numReqs < 1 || numReqs > 2 {
2398 t.Fatalf("%d. bug in test. unexpected number of requests = %d", i, numReqs)
2399 }
2400 didSearch := size0 != size1
2401 if didSearch != tt.wantEOFSearch {
2402 t.Errorf("%d. did EOF search = %v; want %v (size went from %d to %d)", i, didSearch, !didSearch, size0, size1)
2403 }
2404 if tt.wantNextReq && numReqs != 2 {
2405 t.Errorf("%d. numReq = %d; want 2", i, numReqs)
2406 }
2407 }
2408
2409
2410
2411 type testHandlerBodyConsumer struct {
2412 name string
2413 f func(io.ReadCloser)
2414 }
2415
2416 var testHandlerBodyConsumers = []testHandlerBodyConsumer{
2417 {"nil", func(io.ReadCloser) {}},
2418 {"close", func(r io.ReadCloser) { r.Close() }},
2419 {"discard", func(r io.ReadCloser) { io.Copy(io.Discard, r) }},
2420 }
2421
2422 func TestRequestBodyReadErrorClosesConnection(t *testing.T) {
2423 setParallel(t)
2424 defer afterTest(t)
2425 for _, handler := range testHandlerBodyConsumers {
2426 conn := new(testConn)
2427 conn.readBuf.WriteString("POST /public HTTP/1.1\r\n" +
2428 "Host: test\r\n" +
2429 "Transfer-Encoding: chunked\r\n" +
2430 "\r\n" +
2431 "hax\r\n" +
2432 "GET /secret HTTP/1.1\r\n" +
2433 "Host: test\r\n" +
2434 "\r\n")
2435
2436 conn.closec = make(chan bool, 1)
2437 ls := &oneConnListener{conn}
2438 var numReqs int
2439 go Serve(ls, HandlerFunc(func(_ ResponseWriter, req *Request) {
2440 numReqs++
2441 if strings.Contains(req.URL.Path, "secret") {
2442 t.Error("Request for /secret encountered, should not have happened.")
2443 }
2444 handler.f(req.Body)
2445 }))
2446 <-conn.closec
2447 if numReqs != 1 {
2448 t.Errorf("Handler %v: got %d reqs; want 1", handler.name, numReqs)
2449 }
2450 }
2451 }
2452
2453 func TestInvalidTrailerClosesConnection(t *testing.T) {
2454 setParallel(t)
2455 defer afterTest(t)
2456 for _, handler := range testHandlerBodyConsumers {
2457 conn := new(testConn)
2458 conn.readBuf.WriteString("POST /public HTTP/1.1\r\n" +
2459 "Host: test\r\n" +
2460 "Trailer: hack\r\n" +
2461 "Transfer-Encoding: chunked\r\n" +
2462 "\r\n" +
2463 "3\r\n" +
2464 "hax\r\n" +
2465 "0\r\n" +
2466 "I'm not a valid trailer\r\n" +
2467 "GET /secret HTTP/1.1\r\n" +
2468 "Host: test\r\n" +
2469 "\r\n")
2470
2471 conn.closec = make(chan bool, 1)
2472 ln := &oneConnListener{conn}
2473 var numReqs int
2474 go Serve(ln, HandlerFunc(func(_ ResponseWriter, req *Request) {
2475 numReqs++
2476 if strings.Contains(req.URL.Path, "secret") {
2477 t.Errorf("Handler %s, Request for /secret encountered, should not have happened.", handler.name)
2478 }
2479 handler.f(req.Body)
2480 }))
2481 <-conn.closec
2482 if numReqs != 1 {
2483 t.Errorf("Handler %s: got %d reqs; want 1", handler.name, numReqs)
2484 }
2485 }
2486 }
2487
2488
2489
2490
2491 type slowTestConn struct {
2492
2493 script []any
2494 closec chan bool
2495
2496 mu sync.Mutex
2497 rd, wd time.Time
2498 noopConn
2499 }
2500
2501 func (c *slowTestConn) SetDeadline(t time.Time) error {
2502 c.SetReadDeadline(t)
2503 c.SetWriteDeadline(t)
2504 return nil
2505 }
2506
2507 func (c *slowTestConn) SetReadDeadline(t time.Time) error {
2508 c.mu.Lock()
2509 defer c.mu.Unlock()
2510 c.rd = t
2511 return nil
2512 }
2513
2514 func (c *slowTestConn) SetWriteDeadline(t time.Time) error {
2515 c.mu.Lock()
2516 defer c.mu.Unlock()
2517 c.wd = t
2518 return nil
2519 }
2520
2521 func (c *slowTestConn) Read(b []byte) (n int, err error) {
2522 c.mu.Lock()
2523 defer c.mu.Unlock()
2524 restart:
2525 if !c.rd.IsZero() && time.Now().After(c.rd) {
2526 return 0, syscall.ETIMEDOUT
2527 }
2528 if len(c.script) == 0 {
2529 return 0, io.EOF
2530 }
2531
2532 switch cue := c.script[0].(type) {
2533 case time.Duration:
2534 if !c.rd.IsZero() {
2535
2536
2537 if remaining := time.Until(c.rd); remaining < cue {
2538 c.script[0] = cue - remaining
2539 time.Sleep(remaining)
2540 return 0, syscall.ETIMEDOUT
2541 }
2542 }
2543 c.script = c.script[1:]
2544 time.Sleep(cue)
2545 goto restart
2546
2547 case string:
2548 n = copy(b, cue)
2549
2550 if len(cue) > n {
2551 c.script[0] = cue[n:]
2552 } else {
2553 c.script = c.script[1:]
2554 }
2555
2556 default:
2557 panic("unknown cue in slowTestConn script")
2558 }
2559
2560 return
2561 }
2562
2563 func (c *slowTestConn) Close() error {
2564 select {
2565 case c.closec <- true:
2566 default:
2567 }
2568 return nil
2569 }
2570
2571 func (c *slowTestConn) Write(b []byte) (int, error) {
2572 if !c.wd.IsZero() && time.Now().After(c.wd) {
2573 return 0, syscall.ETIMEDOUT
2574 }
2575 return len(b), nil
2576 }
2577
2578 func TestRequestBodyTimeoutClosesConnection(t *testing.T) {
2579 if testing.Short() {
2580 t.Skip("skipping in -short mode")
2581 }
2582 defer afterTest(t)
2583 for _, handler := range testHandlerBodyConsumers {
2584 conn := &slowTestConn{
2585 script: []any{
2586 "POST /public HTTP/1.1\r\n" +
2587 "Host: test\r\n" +
2588 "Content-Length: 10000\r\n" +
2589 "\r\n",
2590 "foo bar baz",
2591 600 * time.Millisecond,
2592 "GET /secret HTTP/1.1\r\n" +
2593 "Host: test\r\n" +
2594 "\r\n",
2595 },
2596 closec: make(chan bool, 1),
2597 }
2598 ls := &oneConnListener{conn}
2599
2600 var numReqs int
2601 s := Server{
2602 Handler: HandlerFunc(func(_ ResponseWriter, req *Request) {
2603 numReqs++
2604 if strings.Contains(req.URL.Path, "secret") {
2605 t.Error("Request for /secret encountered, should not have happened.")
2606 }
2607 handler.f(req.Body)
2608 }),
2609 ReadTimeout: 400 * time.Millisecond,
2610 }
2611 go s.Serve(ls)
2612 <-conn.closec
2613
2614 if numReqs != 1 {
2615 t.Errorf("Handler %v: got %d reqs; want 1", handler.name, numReqs)
2616 }
2617 }
2618 }
2619
2620
2621 type cancelableTimeoutContext struct {
2622 context.Context
2623 }
2624
2625 func (c cancelableTimeoutContext) Err() error {
2626 if c.Context.Err() != nil {
2627 return context.DeadlineExceeded
2628 }
2629 return nil
2630 }
2631
2632 func TestTimeoutHandler(t *testing.T) { run(t, testTimeoutHandler) }
2633 func testTimeoutHandler(t *testing.T, mode testMode) {
2634 sendHi := make(chan bool, 1)
2635 writeErrors := make(chan error, 1)
2636 sayHi := HandlerFunc(func(w ResponseWriter, r *Request) {
2637 <-sendHi
2638 _, werr := w.Write([]byte("hi"))
2639 writeErrors <- werr
2640 })
2641 ctx, cancel := context.WithCancel(context.Background())
2642 h := NewTestTimeoutHandler(sayHi, cancelableTimeoutContext{ctx})
2643 cst := newClientServerTest(t, mode, h)
2644
2645
2646 sendHi <- true
2647 res, err := cst.c.Get(cst.ts.URL)
2648 if err != nil {
2649 t.Error(err)
2650 }
2651 if g, e := res.StatusCode, StatusOK; g != e {
2652 t.Errorf("got res.StatusCode %d; expected %d", g, e)
2653 }
2654 body, _ := io.ReadAll(res.Body)
2655 if g, e := string(body), "hi"; g != e {
2656 t.Errorf("got body %q; expected %q", g, e)
2657 }
2658 if g := <-writeErrors; g != nil {
2659 t.Errorf("got unexpected Write error on first request: %v", g)
2660 }
2661
2662
2663 cancel()
2664
2665 res, err = cst.c.Get(cst.ts.URL)
2666 if err != nil {
2667 t.Error(err)
2668 }
2669 if g, e := res.StatusCode, StatusServiceUnavailable; g != e {
2670 t.Errorf("got res.StatusCode %d; expected %d", g, e)
2671 }
2672 body, _ = io.ReadAll(res.Body)
2673 if !strings.Contains(string(body), "<title>Timeout</title>") {
2674 t.Errorf("expected timeout body; got %q", string(body))
2675 }
2676 if g, w := res.Header.Get("Content-Type"), "text/html; charset=utf-8"; g != w {
2677 t.Errorf("response content-type = %q; want %q", g, w)
2678 }
2679
2680
2681
2682 sendHi <- true
2683 if g, e := <-writeErrors, ErrHandlerTimeout; g != e {
2684 t.Errorf("expected Write error of %v; got %v", e, g)
2685 }
2686 }
2687
2688
2689 func TestTimeoutHandlerRace(t *testing.T) { run(t, testTimeoutHandlerRace) }
2690 func testTimeoutHandlerRace(t *testing.T, mode testMode) {
2691 delayHi := HandlerFunc(func(w ResponseWriter, r *Request) {
2692 ms, _ := strconv.Atoi(r.URL.Path[1:])
2693 if ms == 0 {
2694 ms = 1
2695 }
2696 for i := 0; i < ms; i++ {
2697 w.Write([]byte("hi"))
2698 time.Sleep(time.Millisecond)
2699 }
2700 })
2701
2702 ts := newClientServerTest(t, mode, TimeoutHandler(delayHi, 20*time.Millisecond, "")).ts
2703
2704 c := ts.Client()
2705
2706 var wg sync.WaitGroup
2707 gate := make(chan bool, 10)
2708 n := 50
2709 if testing.Short() {
2710 n = 10
2711 gate = make(chan bool, 3)
2712 }
2713 for i := 0; i < n; i++ {
2714 gate <- true
2715 wg.Add(1)
2716 go func() {
2717 defer wg.Done()
2718 defer func() { <-gate }()
2719 res, err := c.Get(fmt.Sprintf("%s/%d", ts.URL, rand.Intn(50)))
2720 if err == nil {
2721 io.Copy(io.Discard, res.Body)
2722 res.Body.Close()
2723 }
2724 }()
2725 }
2726 wg.Wait()
2727 }
2728
2729
2730
2731 func TestTimeoutHandlerRaceHeader(t *testing.T) { run(t, testTimeoutHandlerRaceHeader) }
2732 func testTimeoutHandlerRaceHeader(t *testing.T, mode testMode) {
2733 delay204 := HandlerFunc(func(w ResponseWriter, r *Request) {
2734 w.WriteHeader(204)
2735 })
2736
2737 ts := newClientServerTest(t, mode, TimeoutHandler(delay204, time.Nanosecond, "")).ts
2738
2739 var wg sync.WaitGroup
2740 gate := make(chan bool, 50)
2741 n := 500
2742 if testing.Short() {
2743 n = 10
2744 }
2745
2746 c := ts.Client()
2747 for i := 0; i < n; i++ {
2748 gate <- true
2749 wg.Add(1)
2750 go func() {
2751 defer wg.Done()
2752 defer func() { <-gate }()
2753 res, err := c.Get(ts.URL)
2754 if err != nil {
2755
2756
2757 t.Log(err)
2758 return
2759 }
2760 defer res.Body.Close()
2761 io.Copy(io.Discard, res.Body)
2762 }()
2763 }
2764 wg.Wait()
2765 }
2766
2767
2768 func TestTimeoutHandlerRaceHeaderTimeout(t *testing.T) { run(t, testTimeoutHandlerRaceHeaderTimeout) }
2769 func testTimeoutHandlerRaceHeaderTimeout(t *testing.T, mode testMode) {
2770 sendHi := make(chan bool, 1)
2771 writeErrors := make(chan error, 1)
2772 sayHi := HandlerFunc(func(w ResponseWriter, r *Request) {
2773 w.Header().Set("Content-Type", "text/plain")
2774 <-sendHi
2775 _, werr := w.Write([]byte("hi"))
2776 writeErrors <- werr
2777 })
2778 ctx, cancel := context.WithCancel(context.Background())
2779 h := NewTestTimeoutHandler(sayHi, cancelableTimeoutContext{ctx})
2780 cst := newClientServerTest(t, mode, h)
2781
2782
2783 sendHi <- true
2784 res, err := cst.c.Get(cst.ts.URL)
2785 if err != nil {
2786 t.Error(err)
2787 }
2788 if g, e := res.StatusCode, StatusOK; g != e {
2789 t.Errorf("got res.StatusCode %d; expected %d", g, e)
2790 }
2791 body, _ := io.ReadAll(res.Body)
2792 if g, e := string(body), "hi"; g != e {
2793 t.Errorf("got body %q; expected %q", g, e)
2794 }
2795 if g := <-writeErrors; g != nil {
2796 t.Errorf("got unexpected Write error on first request: %v", g)
2797 }
2798
2799
2800 cancel()
2801
2802 res, err = cst.c.Get(cst.ts.URL)
2803 if err != nil {
2804 t.Error(err)
2805 }
2806 if g, e := res.StatusCode, StatusServiceUnavailable; g != e {
2807 t.Errorf("got res.StatusCode %d; expected %d", g, e)
2808 }
2809 body, _ = io.ReadAll(res.Body)
2810 if !strings.Contains(string(body), "<title>Timeout</title>") {
2811 t.Errorf("expected timeout body; got %q", string(body))
2812 }
2813
2814
2815
2816 sendHi <- true
2817 if g, e := <-writeErrors, ErrHandlerTimeout; g != e {
2818 t.Errorf("expected Write error of %v; got %v", e, g)
2819 }
2820 }
2821
2822
2823 func TestTimeoutHandlerStartTimerWhenServing(t *testing.T) {
2824 run(t, testTimeoutHandlerStartTimerWhenServing)
2825 }
2826 func testTimeoutHandlerStartTimerWhenServing(t *testing.T, mode testMode) {
2827 if testing.Short() {
2828 t.Skip("skipping sleeping test in -short mode")
2829 }
2830 var handler HandlerFunc = func(w ResponseWriter, _ *Request) {
2831 w.WriteHeader(StatusNoContent)
2832 }
2833 timeout := 300 * time.Millisecond
2834 ts := newClientServerTest(t, mode, TimeoutHandler(handler, timeout, "")).ts
2835 defer ts.Close()
2836
2837 c := ts.Client()
2838
2839
2840
2841
2842 time.Sleep(2 * timeout)
2843 res, err := c.Get(ts.URL)
2844 if err != nil {
2845 t.Fatal(err)
2846 }
2847 defer res.Body.Close()
2848 if res.StatusCode != StatusNoContent {
2849 t.Errorf("got res.StatusCode %d, want %v", res.StatusCode, StatusNoContent)
2850 }
2851 }
2852
2853 func TestTimeoutHandlerContextCanceled(t *testing.T) { run(t, testTimeoutHandlerContextCanceled) }
2854 func testTimeoutHandlerContextCanceled(t *testing.T, mode testMode) {
2855 writeErrors := make(chan error, 1)
2856 sayHi := HandlerFunc(func(w ResponseWriter, r *Request) {
2857 w.Header().Set("Content-Type", "text/plain")
2858 var err error
2859
2860
2861
2862 for i := 0; i < 100; i++ {
2863 _, err = w.Write([]byte("a"))
2864 if err != nil {
2865 break
2866 }
2867 time.Sleep(1 * time.Millisecond)
2868 }
2869 writeErrors <- err
2870 })
2871 ctx, cancel := context.WithCancel(context.Background())
2872 cancel()
2873 h := NewTestTimeoutHandler(sayHi, ctx)
2874 cst := newClientServerTest(t, mode, h)
2875 defer cst.close()
2876
2877 res, err := cst.c.Get(cst.ts.URL)
2878 if err != nil {
2879 t.Error(err)
2880 }
2881 if g, e := res.StatusCode, StatusServiceUnavailable; g != e {
2882 t.Errorf("got res.StatusCode %d; expected %d", g, e)
2883 }
2884 body, _ := io.ReadAll(res.Body)
2885 if g, e := string(body), ""; g != e {
2886 t.Errorf("got body %q; expected %q", g, e)
2887 }
2888 if g, e := <-writeErrors, context.Canceled; g != e {
2889 t.Errorf("got unexpected Write in handler: %v, want %g", g, e)
2890 }
2891 }
2892
2893
2894 func TestTimeoutHandlerEmptyResponse(t *testing.T) { run(t, testTimeoutHandlerEmptyResponse) }
2895 func testTimeoutHandlerEmptyResponse(t *testing.T, mode testMode) {
2896 var handler HandlerFunc = func(w ResponseWriter, _ *Request) {
2897
2898 }
2899 timeout := 300 * time.Millisecond
2900 ts := newClientServerTest(t, mode, TimeoutHandler(handler, timeout, "")).ts
2901
2902 c := ts.Client()
2903
2904 res, err := c.Get(ts.URL)
2905 if err != nil {
2906 t.Fatal(err)
2907 }
2908 defer res.Body.Close()
2909 if res.StatusCode != StatusOK {
2910 t.Errorf("got res.StatusCode %d, want %v", res.StatusCode, StatusOK)
2911 }
2912 }
2913
2914
2915 func TestTimeoutHandlerPanicRecovery(t *testing.T) {
2916 wrapper := func(h Handler) Handler {
2917 return TimeoutHandler(h, time.Second, "")
2918 }
2919 run(t, func(t *testing.T, mode testMode) {
2920 testHandlerPanic(t, false, mode, wrapper, "intentional death for testing")
2921 }, testNotParallel)
2922 }
2923
2924 func TestRedirectBadPath(t *testing.T) {
2925
2926
2927 rr := httptest.NewRecorder()
2928 req := &Request{
2929 Method: "GET",
2930 URL: &url.URL{
2931 Scheme: "http",
2932 Path: "not-empty-but-no-leading-slash",
2933 },
2934 }
2935 Redirect(rr, req, "", 304)
2936 if rr.Code != 304 {
2937 t.Errorf("Code = %d; want 304", rr.Code)
2938 }
2939 }
2940
2941 func TestRedirectEscapedPath(t *testing.T) {
2942 baseURL, redirectURL := "http://example.com/foo%2Fbar/", "qux%2Fbaz"
2943 req := httptest.NewRequest("GET", baseURL, NoBody)
2944
2945 rr := httptest.NewRecorder()
2946 Redirect(rr, req, redirectURL, StatusMovedPermanently)
2947
2948 wantURL := "/foo%2Fbar/qux%2Fbaz"
2949 if got := rr.Result().Header.Get("Location"); got != wantURL {
2950 t.Errorf("Redirect(%s, %s) = %s, want = %s", baseURL, redirectURL, got, wantURL)
2951 }
2952 }
2953
2954
2955 func TestRedirect(t *testing.T) {
2956 req, _ := NewRequest("GET", "http://example.com/qux/", nil)
2957
2958 var tests = []struct {
2959 in string
2960 want string
2961 }{
2962
2963 {"http://foobar.com/baz", "http://foobar.com/baz"},
2964
2965 {"https://foobar.com/baz", "https://foobar.com/baz"},
2966
2967 {"test://foobar.com/baz", "test://foobar.com/baz"},
2968
2969 {"//foobar.com/baz", "//foobar.com/baz"},
2970
2971 {"/foobar.com/baz", "/foobar.com/baz"},
2972
2973 {"foobar.com/baz", "/qux/foobar.com/baz"},
2974
2975 {"../quux/foobar.com/baz", "/quux/foobar.com/baz"},
2976
2977 {"///foobar.com/baz", "/foobar.com/baz"},
2978
2979
2980 {"/foo?next=http://bar.com/", "/foo?next=http://bar.com/"},
2981 {"http://localhost:8080/_ah/login?continue=http://localhost:8080/",
2982 "http://localhost:8080/_ah/login?continue=http://localhost:8080/"},
2983
2984 {"/фубар", "/%d1%84%d1%83%d0%b1%d0%b0%d1%80"},
2985 {"http://foo.com/фубар", "http://foo.com/%d1%84%d1%83%d0%b1%d0%b0%d1%80"},
2986 }
2987
2988 for _, tt := range tests {
2989 rec := httptest.NewRecorder()
2990 Redirect(rec, req, tt.in, 302)
2991 if got, want := rec.Code, 302; got != want {
2992 t.Errorf("Redirect(%q) generated status code %v; want %v", tt.in, got, want)
2993 }
2994 if got := rec.Header().Get("Location"); got != tt.want {
2995 t.Errorf("Redirect(%q) generated Location header %q; want %q", tt.in, got, tt.want)
2996 }
2997 }
2998 }
2999
3000
3001
3002 func TestRedirectContentTypeAndBody(t *testing.T) {
3003 type ctHeader struct {
3004 Values []string
3005 }
3006
3007 var tests = []struct {
3008 method string
3009 ct *ctHeader
3010 wantCT string
3011 wantBody string
3012 }{
3013 {MethodGet, nil, "text/html; charset=utf-8", "<a href=\"/foo\">Found</a>.\n\n"},
3014 {MethodHead, nil, "text/html; charset=utf-8", ""},
3015 {MethodPost, nil, "", ""},
3016 {MethodDelete, nil, "", ""},
3017 {"foo", nil, "", ""},
3018 {MethodGet, &ctHeader{[]string{"application/test"}}, "application/test", ""},
3019 {MethodGet, &ctHeader{[]string{}}, "", ""},
3020 {MethodGet, &ctHeader{nil}, "", ""},
3021 }
3022 for _, tt := range tests {
3023 req := httptest.NewRequest(tt.method, "http://example.com/qux/", nil)
3024 rec := httptest.NewRecorder()
3025 if tt.ct != nil {
3026 rec.Header()["Content-Type"] = tt.ct.Values
3027 }
3028 Redirect(rec, req, "/foo", 302)
3029 if got, want := rec.Code, 302; got != want {
3030 t.Errorf("Redirect(%q, %#v) generated status code %v; want %v", tt.method, tt.ct, got, want)
3031 }
3032 if got, want := rec.Header().Get("Content-Type"), tt.wantCT; got != want {
3033 t.Errorf("Redirect(%q, %#v) generated Content-Type header %q; want %q", tt.method, tt.ct, got, want)
3034 }
3035 resp := rec.Result()
3036 body, err := io.ReadAll(resp.Body)
3037 if err != nil {
3038 t.Fatal(err)
3039 }
3040 if got, want := string(body), tt.wantBody; got != want {
3041 t.Errorf("Redirect(%q, %#v) generated Body %q; want %q", tt.method, tt.ct, got, want)
3042 }
3043 }
3044 }
3045
3046
3047
3048
3049
3050
3051
3052 func TestZeroLengthPostAndResponse(t *testing.T) { run(t, testZeroLengthPostAndResponse) }
3053
3054 func testZeroLengthPostAndResponse(t *testing.T, mode testMode) {
3055 cst := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, r *Request) {
3056 all, err := io.ReadAll(r.Body)
3057 if err != nil {
3058 t.Fatalf("handler ReadAll: %v", err)
3059 }
3060 if len(all) != 0 {
3061 t.Errorf("handler got %d bytes; expected 0", len(all))
3062 }
3063 rw.Header().Set("Content-Length", "0")
3064 }))
3065
3066 req, err := NewRequest("POST", cst.ts.URL, strings.NewReader(""))
3067 if err != nil {
3068 t.Fatal(err)
3069 }
3070 req.ContentLength = 0
3071
3072 var resp [5]*Response
3073 for i := range resp {
3074 resp[i], err = cst.c.Do(req)
3075 if err != nil {
3076 t.Fatalf("client post #%d: %v", i, err)
3077 }
3078 }
3079
3080 for i := range resp {
3081 all, err := io.ReadAll(resp[i].Body)
3082 if err != nil {
3083 t.Fatalf("req #%d: client ReadAll: %v", i, err)
3084 }
3085 if len(all) != 0 {
3086 t.Errorf("req #%d: client got %d bytes; expected 0", i, len(all))
3087 }
3088 }
3089 }
3090
3091 func TestHandlerPanicNil(t *testing.T) {
3092 run(t, func(t *testing.T, mode testMode) {
3093 testHandlerPanic(t, false, mode, nil, nil)
3094 }, testNotParallel)
3095 }
3096
3097 func TestHandlerPanic(t *testing.T) {
3098 run(t, func(t *testing.T, mode testMode) {
3099 testHandlerPanic(t, false, mode, nil, "intentional death for testing")
3100 }, testNotParallel)
3101 }
3102
3103 func TestHandlerPanicWithHijack(t *testing.T) {
3104
3105 run(t, func(t *testing.T, mode testMode) {
3106 testHandlerPanic(t, true, mode, nil, "intentional death for testing")
3107 }, []testMode{http1Mode})
3108 }
3109
3110 func testHandlerPanic(t *testing.T, withHijack bool, mode testMode, wrapper func(Handler) Handler, panicValue any) {
3111
3112
3113
3114
3115
3116
3117
3118
3119 pr, pw := io.Pipe()
3120 defer pw.Close()
3121
3122 var handler Handler = HandlerFunc(func(w ResponseWriter, r *Request) {
3123 if withHijack {
3124 rwc, _, err := w.(Hijacker).Hijack()
3125 if err != nil {
3126 t.Logf("unexpected error: %v", err)
3127 }
3128 defer rwc.Close()
3129 }
3130 panic(panicValue)
3131 })
3132 if wrapper != nil {
3133 handler = wrapper(handler)
3134 }
3135 cst := newClientServerTest(t, mode, handler, func(ts *httptest.Server) {
3136 ts.Config.ErrorLog = log.New(pw, "", 0)
3137 })
3138
3139
3140 done := make(chan bool, 1)
3141 go func() {
3142 buf := make([]byte, 4<<10)
3143 _, err := pr.Read(buf)
3144 pr.Close()
3145 if err != nil && err != io.EOF {
3146 t.Error(err)
3147 }
3148 done <- true
3149 }()
3150
3151 _, err := cst.c.Get(cst.ts.URL)
3152 if err == nil {
3153 t.Logf("expected an error")
3154 }
3155
3156 if panicValue == nil {
3157 return
3158 }
3159
3160 <-done
3161 }
3162
3163 type terrorWriter struct{ t *testing.T }
3164
3165 func (w terrorWriter) Write(p []byte) (int, error) {
3166 w.t.Errorf("%s", p)
3167 return len(p), nil
3168 }
3169
3170
3171
3172 func TestServerWriteHijackZeroBytes(t *testing.T) {
3173 run(t, testServerWriteHijackZeroBytes, []testMode{http1Mode})
3174 }
3175 func testServerWriteHijackZeroBytes(t *testing.T, mode testMode) {
3176 done := make(chan struct{})
3177 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
3178 defer close(done)
3179 w.(Flusher).Flush()
3180 conn, _, err := w.(Hijacker).Hijack()
3181 if err != nil {
3182 t.Errorf("Hijack: %v", err)
3183 return
3184 }
3185 defer conn.Close()
3186 _, err = w.Write(nil)
3187 if err != ErrHijacked {
3188 t.Errorf("Write error = %v; want ErrHijacked", err)
3189 }
3190 }), func(ts *httptest.Server) {
3191 ts.Config.ErrorLog = log.New(terrorWriter{t}, "Unexpected write: ", 0)
3192 }).ts
3193
3194 c := ts.Client()
3195 res, err := c.Get(ts.URL)
3196 if err != nil {
3197 t.Fatal(err)
3198 }
3199 res.Body.Close()
3200 <-done
3201 }
3202
3203 func TestServerNoDate(t *testing.T) {
3204 run(t, func(t *testing.T, mode testMode) {
3205 testServerNoHeader(t, mode, "Date")
3206 })
3207 }
3208
3209 func TestServerContentType(t *testing.T) {
3210 run(t, func(t *testing.T, mode testMode) {
3211 testServerNoHeader(t, mode, "Content-Type")
3212 })
3213 }
3214
3215 func testServerNoHeader(t *testing.T, mode testMode, header string) {
3216 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
3217 w.Header()[header] = nil
3218 io.WriteString(w, "<html>foo</html>")
3219 }))
3220 res, err := cst.c.Get(cst.ts.URL)
3221 if err != nil {
3222 t.Fatal(err)
3223 }
3224 res.Body.Close()
3225 if got, ok := res.Header[header]; ok {
3226 t.Fatalf("Expected no %s header; got %q", header, got)
3227 }
3228 }
3229
3230 func TestStripPrefix(t *testing.T) { run(t, testStripPrefix) }
3231 func testStripPrefix(t *testing.T, mode testMode) {
3232 h := HandlerFunc(func(w ResponseWriter, r *Request) {
3233 w.Header().Set("X-Path", r.URL.Path)
3234 w.Header().Set("X-RawPath", r.URL.RawPath)
3235 })
3236 ts := newClientServerTest(t, mode, StripPrefix("/foo/bar", h)).ts
3237
3238 c := ts.Client()
3239
3240 cases := []struct {
3241 reqPath string
3242 path string
3243 rawPath string
3244 }{
3245 {"/foo/bar/qux", "/qux", ""},
3246 {"/foo/bar%2Fqux", "/qux", "%2Fqux"},
3247 {"/foo%2Fbar/qux", "", ""},
3248 {"/bar", "", ""},
3249 }
3250 for _, tc := range cases {
3251 t.Run(tc.reqPath, func(t *testing.T) {
3252 res, err := c.Get(ts.URL + tc.reqPath)
3253 if err != nil {
3254 t.Fatal(err)
3255 }
3256 res.Body.Close()
3257 if tc.path == "" {
3258 if res.StatusCode != StatusNotFound {
3259 t.Errorf("got %q, want 404 Not Found", res.Status)
3260 }
3261 return
3262 }
3263 if res.StatusCode != StatusOK {
3264 t.Fatalf("got %q, want 200 OK", res.Status)
3265 }
3266 if g, w := res.Header.Get("X-Path"), tc.path; g != w {
3267 t.Errorf("got Path %q, want %q", g, w)
3268 }
3269 if g, w := res.Header.Get("X-RawPath"), tc.rawPath; g != w {
3270 t.Errorf("got RawPath %q, want %q", g, w)
3271 }
3272 })
3273 }
3274 }
3275
3276
3277 func TestStripPrefixNotModifyRequest(t *testing.T) {
3278 h := StripPrefix("/foo", NotFoundHandler())
3279 req := httptest.NewRequest("GET", "/foo/bar", nil)
3280 h.ServeHTTP(httptest.NewRecorder(), req)
3281 if req.URL.Path != "/foo/bar" {
3282 t.Errorf("StripPrefix should not modify the provided Request, but it did")
3283 }
3284 }
3285
3286 func TestRequestLimit(t *testing.T) { run(t, testRequestLimit) }
3287 func testRequestLimit(t *testing.T, mode testMode) {
3288 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
3289 t.Fatalf("didn't expect to get request in Handler")
3290 }), optQuietLog)
3291 req, _ := NewRequest("GET", cst.ts.URL, nil)
3292 var bytesPerHeader = len("header12345: val12345\r\n")
3293 for i := 0; i < ((DefaultMaxHeaderBytes+4096)/bytesPerHeader)+1; i++ {
3294 req.Header.Set(fmt.Sprintf("header%05d", i), fmt.Sprintf("val%05d", i))
3295 }
3296 res, err := cst.c.Do(req)
3297 if res != nil {
3298 defer res.Body.Close()
3299 }
3300 if mode == http2Mode {
3301
3302
3303
3304
3305 if err == nil && res.StatusCode != 431 {
3306 t.Fatalf("expected 431 response status; got: %d %s", res.StatusCode, res.Status)
3307 }
3308 } else {
3309
3310
3311
3312
3313 if err != nil {
3314 t.Fatalf("Do: %v", err)
3315 }
3316 if res.StatusCode != 431 {
3317 t.Fatalf("expected 431 response status; got: %d %s", res.StatusCode, res.Status)
3318 }
3319 }
3320 }
3321
3322 type neverEnding byte
3323
3324 func (b neverEnding) Read(p []byte) (n int, err error) {
3325 for i := range p {
3326 p[i] = byte(b)
3327 }
3328 return len(p), nil
3329 }
3330
3331 type bodyLimitReader struct {
3332 mu sync.Mutex
3333 count int
3334 limit int
3335 closed chan struct{}
3336 }
3337
3338 func (r *bodyLimitReader) Read(p []byte) (int, error) {
3339 r.mu.Lock()
3340 defer r.mu.Unlock()
3341 select {
3342 case <-r.closed:
3343 return 0, errors.New("closed")
3344 default:
3345 }
3346 if r.count > r.limit {
3347 return 0, errors.New("at limit")
3348 }
3349 r.count += len(p)
3350 for i := range p {
3351 p[i] = 'a'
3352 }
3353 return len(p), nil
3354 }
3355
3356 func (r *bodyLimitReader) Close() error {
3357 r.mu.Lock()
3358 defer r.mu.Unlock()
3359 close(r.closed)
3360 return nil
3361 }
3362
3363 func TestRequestBodyLimit(t *testing.T) { run(t, testRequestBodyLimit) }
3364 func testRequestBodyLimit(t *testing.T, mode testMode) {
3365 const limit = 1 << 20
3366 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
3367 r.Body = MaxBytesReader(w, r.Body, limit)
3368 n, err := io.Copy(io.Discard, r.Body)
3369 if err == nil {
3370 t.Errorf("expected error from io.Copy")
3371 }
3372 if n != limit {
3373 t.Errorf("io.Copy = %d, want %d", n, limit)
3374 }
3375 mbErr, ok := err.(*MaxBytesError)
3376 if !ok {
3377 t.Errorf("expected MaxBytesError, got %T", err)
3378 }
3379 if mbErr.Limit != limit {
3380 t.Errorf("MaxBytesError.Limit = %d, want %d", mbErr.Limit, limit)
3381 }
3382 }))
3383
3384 body := &bodyLimitReader{
3385 closed: make(chan struct{}),
3386 limit: limit * 200,
3387 }
3388 req, _ := NewRequest("POST", cst.ts.URL, body)
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399 resp, err := cst.c.Do(req)
3400 if err == nil {
3401 resp.Body.Close()
3402 }
3403
3404
3405 <-body.closed
3406
3407 if body.count > limit*100 {
3408 t.Errorf("handler restricted the request body to %d bytes, but client managed to write %d",
3409 limit, body.count)
3410 }
3411 }
3412
3413
3414
3415 func TestClientWriteShutdown(t *testing.T) { run(t, testClientWriteShutdown) }
3416 func testClientWriteShutdown(t *testing.T, mode testMode) {
3417 if runtime.GOOS == "plan9" {
3418 t.Skip("skipping test; see https://golang.org/issue/17906")
3419 }
3420 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {})).ts
3421 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
3422 if err != nil {
3423 t.Fatalf("Dial: %v", err)
3424 }
3425 err = conn.(*net.TCPConn).CloseWrite()
3426 if err != nil {
3427 t.Fatalf("CloseWrite: %v", err)
3428 }
3429
3430 bs, err := io.ReadAll(conn)
3431 if err != nil {
3432 t.Errorf("ReadAll: %v", err)
3433 }
3434 got := string(bs)
3435 if got != "" {
3436 t.Errorf("read %q from server; want nothing", got)
3437 }
3438 }
3439
3440
3441
3442 func TestServerBufferedChunking(t *testing.T) {
3443 conn := new(testConn)
3444 conn.readBuf.Write([]byte("GET / HTTP/1.1\r\nHost: foo\r\n\r\n"))
3445 conn.closec = make(chan bool, 1)
3446 ls := &oneConnListener{conn}
3447 go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
3448 rw.(Flusher).Flush()
3449 rw.Write([]byte{'x'})
3450 rw.Write([]byte{'y'})
3451 rw.Write([]byte{'z'})
3452 }))
3453 <-conn.closec
3454 if !bytes.HasSuffix(conn.writeBuf.Bytes(), []byte("\r\n\r\n3\r\nxyz\r\n0\r\n\r\n")) {
3455 t.Errorf("response didn't end with a single 3 byte 'xyz' chunk; got:\n%q",
3456 conn.writeBuf.Bytes())
3457 }
3458 }
3459
3460
3461
3462
3463
3464 func TestServerGracefulClose(t *testing.T) {
3465
3466 run(t, testServerGracefulClose, []testMode{http1Mode}, testNotParallel)
3467 }
3468 func testServerGracefulClose(t *testing.T, mode testMode) {
3469 runTimeSensitiveTest(t, []time.Duration{
3470 1 * time.Millisecond,
3471 5 * time.Millisecond,
3472 10 * time.Millisecond,
3473 50 * time.Millisecond,
3474 100 * time.Millisecond,
3475 500 * time.Millisecond,
3476 time.Second,
3477 5 * time.Second,
3478 }, func(t *testing.T, timeout time.Duration) error {
3479 SetRSTAvoidanceDelay(t, timeout)
3480 t.Logf("set RST avoidance delay to %v", timeout)
3481
3482 const bodySize = 5 << 20
3483 req := []byte(fmt.Sprintf("POST / HTTP/1.1\r\nHost: foo.com\r\nContent-Length: %d\r\n\r\n", bodySize))
3484 for i := 0; i < bodySize; i++ {
3485 req = append(req, 'x')
3486 }
3487
3488 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
3489 Error(w, "bye", StatusUnauthorized)
3490 }))
3491
3492
3493 defer cst.close()
3494 ts := cst.ts
3495
3496 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
3497 if err != nil {
3498 return err
3499 }
3500 writeErr := make(chan error)
3501 go func() {
3502 _, err := conn.Write(req)
3503 writeErr <- err
3504 }()
3505 defer func() {
3506 conn.Close()
3507
3508
3509
3510 <-writeErr
3511 }()
3512
3513 br := bufio.NewReader(conn)
3514 lineNum := 0
3515 for {
3516 line, err := br.ReadString('\n')
3517 if err == io.EOF {
3518 break
3519 }
3520 if err != nil {
3521 return fmt.Errorf("ReadLine: %v", err)
3522 }
3523 lineNum++
3524 if lineNum == 1 && !strings.Contains(line, "401 Unauthorized") {
3525 t.Errorf("Response line = %q; want a 401", line)
3526 }
3527 }
3528 return nil
3529 })
3530 }
3531
3532 func TestCaseSensitiveMethod(t *testing.T) { run(t, testCaseSensitiveMethod) }
3533 func testCaseSensitiveMethod(t *testing.T, mode testMode) {
3534 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
3535 if r.Method != "get" {
3536 t.Errorf(`Got method %q; want "get"`, r.Method)
3537 }
3538 }))
3539 defer cst.close()
3540 req, _ := NewRequest("get", cst.ts.URL, nil)
3541 res, err := cst.c.Do(req)
3542 if err != nil {
3543 t.Error(err)
3544 return
3545 }
3546
3547 res.Body.Close()
3548 }
3549
3550
3551
3552
3553
3554 func TestContentLengthZero(t *testing.T) {
3555 run(t, testContentLengthZero, []testMode{http1Mode})
3556 }
3557 func testContentLengthZero(t *testing.T, mode testMode) {
3558 ts := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {})).ts
3559
3560 for _, version := range []string{"HTTP/1.0", "HTTP/1.1"} {
3561 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
3562 if err != nil {
3563 t.Fatalf("error dialing: %v", err)
3564 }
3565 _, err = fmt.Fprintf(conn, "GET / %v\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n", version)
3566 if err != nil {
3567 t.Fatalf("error writing: %v", err)
3568 }
3569 req, _ := NewRequest("GET", "/", nil)
3570 res, err := ReadResponse(bufio.NewReader(conn), req)
3571 if err != nil {
3572 t.Fatalf("error reading response: %v", err)
3573 }
3574 if te := res.TransferEncoding; len(te) > 0 {
3575 t.Errorf("For version %q, Transfer-Encoding = %q; want none", version, te)
3576 }
3577 if cl := res.ContentLength; cl != 0 {
3578 t.Errorf("For version %q, Content-Length = %v; want 0", version, cl)
3579 }
3580 conn.Close()
3581 }
3582 }
3583
3584 func TestCloseNotifier(t *testing.T) {
3585 run(t, testCloseNotifier, []testMode{http1Mode})
3586 }
3587 func testCloseNotifier(t *testing.T, mode testMode) {
3588 gotReq := make(chan bool, 1)
3589 sawClose := make(chan bool, 1)
3590 ts := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
3591 gotReq <- true
3592 cc := rw.(CloseNotifier).CloseNotify()
3593 <-cc
3594 sawClose <- true
3595 })).ts
3596 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
3597 if err != nil {
3598 t.Fatalf("error dialing: %v", err)
3599 }
3600 diec := make(chan bool)
3601 go func() {
3602 _, err = fmt.Fprintf(conn, "GET / HTTP/1.1\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n")
3603 if err != nil {
3604 t.Error(err)
3605 return
3606 }
3607 <-diec
3608 conn.Close()
3609 }()
3610 For:
3611 for {
3612 select {
3613 case <-gotReq:
3614 diec <- true
3615 case <-sawClose:
3616 break For
3617 }
3618 }
3619 ts.Close()
3620 }
3621
3622
3623
3624
3625
3626 func TestCloseNotifierPipelined(t *testing.T) {
3627 run(t, testCloseNotifierPipelined, []testMode{http1Mode})
3628 }
3629 func testCloseNotifierPipelined(t *testing.T, mode testMode) {
3630 gotReq := make(chan bool, 2)
3631 sawClose := make(chan bool, 2)
3632 ts := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
3633 gotReq <- true
3634 cc := rw.(CloseNotifier).CloseNotify()
3635 select {
3636 case <-cc:
3637 t.Error("unexpected CloseNotify")
3638 case <-time.After(100 * time.Millisecond):
3639 }
3640 sawClose <- true
3641 })).ts
3642 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
3643 if err != nil {
3644 t.Fatalf("error dialing: %v", err)
3645 }
3646 diec := make(chan bool, 1)
3647 defer close(diec)
3648 go func() {
3649 const req = "GET / HTTP/1.1\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n"
3650 _, err = io.WriteString(conn, req+req)
3651 if err != nil {
3652 t.Error(err)
3653 return
3654 }
3655 <-diec
3656 conn.Close()
3657 }()
3658 reqs := 0
3659 closes := 0
3660 for {
3661 select {
3662 case <-gotReq:
3663 reqs++
3664 if reqs > 2 {
3665 t.Fatal("too many requests")
3666 }
3667 case <-sawClose:
3668 closes++
3669 if closes > 1 {
3670 return
3671 }
3672 }
3673 }
3674 }
3675
3676 func TestCloseNotifierChanLeak(t *testing.T) {
3677 defer afterTest(t)
3678 req := reqBytes("GET / HTTP/1.0\nHost: golang.org")
3679 for i := 0; i < 20; i++ {
3680 var output bytes.Buffer
3681 conn := &rwTestConn{
3682 Reader: bytes.NewReader(req),
3683 Writer: &output,
3684 closec: make(chan bool, 1),
3685 }
3686 ln := &oneConnListener{conn: conn}
3687 handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
3688
3689
3690
3691 _ = rw.(CloseNotifier).CloseNotify()
3692 })
3693 go Serve(ln, handler)
3694 <-conn.closec
3695 }
3696 }
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707 func TestHijackAfterCloseNotifier(t *testing.T) {
3708 run(t, testHijackAfterCloseNotifier, []testMode{http1Mode})
3709 }
3710 func testHijackAfterCloseNotifier(t *testing.T, mode testMode) {
3711 script := make(chan string, 2)
3712 script <- "closenotify"
3713 script <- "hijack"
3714 close(script)
3715 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
3716 plan := <-script
3717 switch plan {
3718 default:
3719 panic("bogus plan; too many requests")
3720 case "closenotify":
3721 w.(CloseNotifier).CloseNotify()
3722 w.Header().Set("X-Addr", r.RemoteAddr)
3723 case "hijack":
3724 c, _, err := w.(Hijacker).Hijack()
3725 if err != nil {
3726 t.Errorf("Hijack in Handler: %v", err)
3727 return
3728 }
3729 if _, ok := c.(*net.TCPConn); !ok {
3730
3731
3732 t.Errorf("type of hijacked conn is %T; want *net.TCPConn", c)
3733 }
3734 fmt.Fprintf(c, "HTTP/1.0 200 OK\r\nX-Addr: %v\r\nContent-Length: 0\r\n\r\n", r.RemoteAddr)
3735 c.Close()
3736 return
3737 }
3738 })).ts
3739 res1, err := ts.Client().Get(ts.URL)
3740 if err != nil {
3741 log.Fatal(err)
3742 }
3743 res2, err := ts.Client().Get(ts.URL)
3744 if err != nil {
3745 log.Fatal(err)
3746 }
3747 addr1 := res1.Header.Get("X-Addr")
3748 addr2 := res2.Header.Get("X-Addr")
3749 if addr1 == "" || addr1 != addr2 {
3750 t.Errorf("addr1, addr2 = %q, %q; want same", addr1, addr2)
3751 }
3752 }
3753
3754 func TestHijackBeforeRequestBodyRead(t *testing.T) {
3755 run(t, testHijackBeforeRequestBodyRead, []testMode{http1Mode})
3756 }
3757 func testHijackBeforeRequestBodyRead(t *testing.T, mode testMode) {
3758 var requestBody = bytes.Repeat([]byte("a"), 1<<20)
3759 bodyOkay := make(chan bool, 1)
3760 gotCloseNotify := make(chan bool, 1)
3761 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
3762 defer close(bodyOkay)
3763
3764 reqBody := r.Body
3765 r.Body = nil
3766
3767 gone := w.(CloseNotifier).CloseNotify()
3768 slurp, err := io.ReadAll(reqBody)
3769 if err != nil {
3770 t.Errorf("Body read: %v", err)
3771 return
3772 }
3773 if len(slurp) != len(requestBody) {
3774 t.Errorf("Backend read %d request body bytes; want %d", len(slurp), len(requestBody))
3775 return
3776 }
3777 if !bytes.Equal(slurp, requestBody) {
3778 t.Error("Backend read wrong request body.")
3779 return
3780 }
3781 bodyOkay <- true
3782 <-gone
3783 gotCloseNotify <- true
3784 })).ts
3785
3786 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
3787 if err != nil {
3788 t.Fatal(err)
3789 }
3790 defer conn.Close()
3791
3792 fmt.Fprintf(conn, "POST / HTTP/1.1\r\nHost: foo\r\nContent-Length: %d\r\n\r\n%s",
3793 len(requestBody), requestBody)
3794 if !<-bodyOkay {
3795
3796 return
3797 }
3798 conn.Close()
3799 <-gotCloseNotify
3800 }
3801
3802 func TestOptions(t *testing.T) { run(t, testOptions, []testMode{http1Mode}) }
3803 func testOptions(t *testing.T, mode testMode) {
3804 uric := make(chan string, 2)
3805 mux := NewServeMux()
3806 mux.HandleFunc("/", func(w ResponseWriter, r *Request) {
3807 uric <- r.RequestURI
3808 })
3809 ts := newClientServerTest(t, mode, mux).ts
3810
3811 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
3812 if err != nil {
3813 t.Fatal(err)
3814 }
3815 defer conn.Close()
3816
3817
3818 _, err = conn.Write([]byte("OPTIONS * HTTP/1.1\r\nHost: foo.com\r\n\r\n"))
3819 if err != nil {
3820 t.Fatal(err)
3821 }
3822 br := bufio.NewReader(conn)
3823 res, err := ReadResponse(br, &Request{Method: "OPTIONS"})
3824 if err != nil {
3825 t.Fatal(err)
3826 }
3827 if res.StatusCode != 200 {
3828 t.Errorf("Got non-200 response to OPTIONS *: %#v", res)
3829 }
3830
3831
3832 _, err = conn.Write([]byte("GET * HTTP/1.1\r\nHost: foo.com\r\n\r\n"))
3833 if err != nil {
3834 t.Fatal(err)
3835 }
3836 res, err = ReadResponse(br, &Request{Method: "GET"})
3837 if err != nil {
3838 t.Fatal(err)
3839 }
3840 if res.StatusCode != 400 {
3841 t.Errorf("Got non-400 response to GET *: %#v", res)
3842 }
3843
3844 res, err = Get(ts.URL + "/second")
3845 if err != nil {
3846 t.Fatal(err)
3847 }
3848 res.Body.Close()
3849 if got := <-uric; got != "/second" {
3850 t.Errorf("Handler saw request for %q; want /second", got)
3851 }
3852 }
3853
3854 func TestOptionsHandler(t *testing.T) { run(t, testOptionsHandler, []testMode{http1Mode}) }
3855 func testOptionsHandler(t *testing.T, mode testMode) {
3856 rc := make(chan *Request, 1)
3857
3858 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
3859 rc <- r
3860 }), func(ts *httptest.Server) {
3861 ts.Config.DisableGeneralOptionsHandler = true
3862 }).ts
3863
3864 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
3865 if err != nil {
3866 t.Fatal(err)
3867 }
3868 defer conn.Close()
3869
3870 _, err = conn.Write([]byte("OPTIONS * HTTP/1.1\r\nHost: foo.com\r\n\r\n"))
3871 if err != nil {
3872 t.Fatal(err)
3873 }
3874
3875 if got := <-rc; got.Method != "OPTIONS" || got.RequestURI != "*" {
3876 t.Errorf("Expected OPTIONS * request, got %v", got)
3877 }
3878 }
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889 func TestHeaderToWire(t *testing.T) {
3890 tests := []struct {
3891 name string
3892 handler func(ResponseWriter, *Request)
3893 check func(got, logs string) error
3894 }{
3895 {
3896 name: "write without Header",
3897 handler: func(rw ResponseWriter, r *Request) {
3898 rw.Write([]byte("hello world"))
3899 },
3900 check: func(got, logs string) error {
3901 if !strings.Contains(got, "Content-Length:") {
3902 return errors.New("no content-length")
3903 }
3904 if !strings.Contains(got, "Content-Type: text/plain") {
3905 return errors.New("no content-type")
3906 }
3907 return nil
3908 },
3909 },
3910 {
3911 name: "Header mutation before write",
3912 handler: func(rw ResponseWriter, r *Request) {
3913 h := rw.Header()
3914 h.Set("Content-Type", "some/type")
3915 rw.Write([]byte("hello world"))
3916 h.Set("Too-Late", "bogus")
3917 },
3918 check: func(got, logs string) error {
3919 if !strings.Contains(got, "Content-Length:") {
3920 return errors.New("no content-length")
3921 }
3922 if !strings.Contains(got, "Content-Type: some/type") {
3923 return errors.New("wrong content-type")
3924 }
3925 if strings.Contains(got, "Too-Late") {
3926 return errors.New("don't want too-late header")
3927 }
3928 return nil
3929 },
3930 },
3931 {
3932 name: "write then useless Header mutation",
3933 handler: func(rw ResponseWriter, r *Request) {
3934 rw.Write([]byte("hello world"))
3935 rw.Header().Set("Too-Late", "Write already wrote headers")
3936 },
3937 check: func(got, logs string) error {
3938 if strings.Contains(got, "Too-Late") {
3939 return errors.New("header appeared from after WriteHeader")
3940 }
3941 return nil
3942 },
3943 },
3944 {
3945 name: "flush then write",
3946 handler: func(rw ResponseWriter, r *Request) {
3947 rw.(Flusher).Flush()
3948 rw.Write([]byte("post-flush"))
3949 rw.Header().Set("Too-Late", "Write already wrote headers")
3950 },
3951 check: func(got, logs string) error {
3952 if !strings.Contains(got, "Transfer-Encoding: chunked") {
3953 return errors.New("not chunked")
3954 }
3955 if strings.Contains(got, "Too-Late") {
3956 return errors.New("header appeared from after WriteHeader")
3957 }
3958 return nil
3959 },
3960 },
3961 {
3962 name: "header then flush",
3963 handler: func(rw ResponseWriter, r *Request) {
3964 rw.Header().Set("Content-Type", "some/type")
3965 rw.(Flusher).Flush()
3966 rw.Write([]byte("post-flush"))
3967 rw.Header().Set("Too-Late", "Write already wrote headers")
3968 },
3969 check: func(got, logs string) error {
3970 if !strings.Contains(got, "Transfer-Encoding: chunked") {
3971 return errors.New("not chunked")
3972 }
3973 if strings.Contains(got, "Too-Late") {
3974 return errors.New("header appeared from after WriteHeader")
3975 }
3976 if !strings.Contains(got, "Content-Type: some/type") {
3977 return errors.New("wrong content-type")
3978 }
3979 return nil
3980 },
3981 },
3982 {
3983 name: "sniff-on-first-write content-type",
3984 handler: func(rw ResponseWriter, r *Request) {
3985 rw.Write([]byte("<html><head></head><body>some html</body></html>"))
3986 rw.Header().Set("Content-Type", "x/wrong")
3987 },
3988 check: func(got, logs string) error {
3989 if !strings.Contains(got, "Content-Type: text/html") {
3990 return errors.New("wrong content-type; want html")
3991 }
3992 return nil
3993 },
3994 },
3995 {
3996 name: "explicit content-type wins",
3997 handler: func(rw ResponseWriter, r *Request) {
3998 rw.Header().Set("Content-Type", "some/type")
3999 rw.Write([]byte("<html><head></head><body>some html</body></html>"))
4000 },
4001 check: func(got, logs string) error {
4002 if !strings.Contains(got, "Content-Type: some/type") {
4003 return errors.New("wrong content-type; want html")
4004 }
4005 return nil
4006 },
4007 },
4008 {
4009 name: "empty handler",
4010 handler: func(rw ResponseWriter, r *Request) {
4011 },
4012 check: func(got, logs string) error {
4013 if !strings.Contains(got, "Content-Length: 0") {
4014 return errors.New("want 0 content-length")
4015 }
4016 return nil
4017 },
4018 },
4019 {
4020 name: "only Header, no write",
4021 handler: func(rw ResponseWriter, r *Request) {
4022 rw.Header().Set("Some-Header", "some-value")
4023 },
4024 check: func(got, logs string) error {
4025 if !strings.Contains(got, "Some-Header") {
4026 return errors.New("didn't get header")
4027 }
4028 return nil
4029 },
4030 },
4031 {
4032 name: "WriteHeader call",
4033 handler: func(rw ResponseWriter, r *Request) {
4034 rw.WriteHeader(404)
4035 rw.Header().Set("Too-Late", "some-value")
4036 },
4037 check: func(got, logs string) error {
4038 if !strings.Contains(got, "404") {
4039 return errors.New("wrong status")
4040 }
4041 if strings.Contains(got, "Too-Late") {
4042 return errors.New("shouldn't have seen Too-Late")
4043 }
4044 return nil
4045 },
4046 },
4047 }
4048 for _, tc := range tests {
4049 ht := newHandlerTest(HandlerFunc(tc.handler))
4050 got := ht.rawResponse("GET / HTTP/1.1\nHost: golang.org")
4051 logs := ht.logbuf.String()
4052 if err := tc.check(got, logs); err != nil {
4053 t.Errorf("%s: %v\nGot response:\n%s\n\n%s", tc.name, err, got, logs)
4054 }
4055 }
4056 }
4057
4058 type errorListener struct {
4059 errs []error
4060 }
4061
4062 func (l *errorListener) Accept() (c net.Conn, err error) {
4063 if len(l.errs) == 0 {
4064 return nil, io.EOF
4065 }
4066 err = l.errs[0]
4067 l.errs = l.errs[1:]
4068 return
4069 }
4070
4071 func (l *errorListener) Close() error {
4072 return nil
4073 }
4074
4075 func (l *errorListener) Addr() net.Addr {
4076 return dummyAddr("test-address")
4077 }
4078
4079 func TestAcceptMaxFds(t *testing.T) {
4080 setParallel(t)
4081
4082 ln := &errorListener{[]error{
4083 &net.OpError{
4084 Op: "accept",
4085 Err: syscall.EMFILE,
4086 }}}
4087 server := &Server{
4088 Handler: HandlerFunc(HandlerFunc(func(ResponseWriter, *Request) {})),
4089 ErrorLog: log.New(io.Discard, "", 0),
4090 }
4091 err := server.Serve(ln)
4092 if err != io.EOF {
4093 t.Errorf("got error %v, want EOF", err)
4094 }
4095 }
4096
4097 func TestWriteAfterHijack(t *testing.T) {
4098 req := reqBytes("GET / HTTP/1.1\nHost: golang.org")
4099 var buf strings.Builder
4100 wrotec := make(chan bool, 1)
4101 conn := &rwTestConn{
4102 Reader: bytes.NewReader(req),
4103 Writer: &buf,
4104 closec: make(chan bool, 1),
4105 }
4106 handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
4107 conn, bufrw, err := rw.(Hijacker).Hijack()
4108 if err != nil {
4109 t.Error(err)
4110 return
4111 }
4112 go func() {
4113 bufrw.Write([]byte("[hijack-to-bufw]"))
4114 bufrw.Flush()
4115 conn.Write([]byte("[hijack-to-conn]"))
4116 conn.Close()
4117 wrotec <- true
4118 }()
4119 })
4120 ln := &oneConnListener{conn: conn}
4121 go Serve(ln, handler)
4122 <-conn.closec
4123 <-wrotec
4124 if g, w := buf.String(), "[hijack-to-bufw][hijack-to-conn]"; g != w {
4125 t.Errorf("wrote %q; want %q", g, w)
4126 }
4127 }
4128
4129 func TestDoubleHijack(t *testing.T) {
4130 req := reqBytes("GET / HTTP/1.1\nHost: golang.org")
4131 var buf bytes.Buffer
4132 conn := &rwTestConn{
4133 Reader: bytes.NewReader(req),
4134 Writer: &buf,
4135 closec: make(chan bool, 1),
4136 }
4137 handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
4138 conn, _, err := rw.(Hijacker).Hijack()
4139 if err != nil {
4140 t.Error(err)
4141 return
4142 }
4143 _, _, err = rw.(Hijacker).Hijack()
4144 if err == nil {
4145 t.Errorf("got err = nil; want err != nil")
4146 }
4147 conn.Close()
4148 })
4149 ln := &oneConnListener{conn: conn}
4150 go Serve(ln, handler)
4151 <-conn.closec
4152 }
4153
4154
4155
4156
4157
4158
4159
4160 func TestHTTP10ConnectionHeader(t *testing.T) {
4161 run(t, testHTTP10ConnectionHeader, []testMode{http1Mode})
4162 }
4163 func testHTTP10ConnectionHeader(t *testing.T, mode testMode) {
4164 mux := NewServeMux()
4165 mux.Handle("/", HandlerFunc(func(ResponseWriter, *Request) {}))
4166 ts := newClientServerTest(t, mode, mux).ts
4167
4168
4169 tests := []struct {
4170 req string
4171 expect []string
4172 }{
4173 {
4174 req: "GET / HTTP/1.0\r\n\r\n",
4175 expect: nil,
4176 },
4177 {
4178 req: "OPTIONS * HTTP/1.0\r\n\r\n",
4179 expect: nil,
4180 },
4181 {
4182 req: "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n",
4183 expect: []string{"keep-alive"},
4184 },
4185 }
4186
4187 for _, tt := range tests {
4188 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
4189 if err != nil {
4190 t.Fatal("dial err:", err)
4191 }
4192
4193 _, err = fmt.Fprint(conn, tt.req)
4194 if err != nil {
4195 t.Fatal("conn write err:", err)
4196 }
4197
4198 resp, err := ReadResponse(bufio.NewReader(conn), &Request{Method: "GET"})
4199 if err != nil {
4200 t.Fatal("ReadResponse err:", err)
4201 }
4202 conn.Close()
4203 resp.Body.Close()
4204
4205 got := resp.Header["Connection"]
4206 if !slices.Equal(got, tt.expect) {
4207 t.Errorf("wrong Connection headers for request %q. Got %q expect %q", tt.req, got, tt.expect)
4208 }
4209 }
4210 }
4211
4212
4213 func TestServerReaderFromOrder(t *testing.T) { run(t, testServerReaderFromOrder) }
4214 func testServerReaderFromOrder(t *testing.T, mode testMode) {
4215 pr, pw := io.Pipe()
4216 const size = 3 << 20
4217 cst := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
4218 rw.Header().Set("Content-Type", "text/plain")
4219 done := make(chan bool)
4220 go func() {
4221 io.Copy(rw, pr)
4222 close(done)
4223 }()
4224 time.Sleep(25 * time.Millisecond)
4225 n, err := io.Copy(io.Discard, req.Body)
4226 if err != nil {
4227 t.Errorf("handler Copy: %v", err)
4228 return
4229 }
4230 if n != size {
4231 t.Errorf("handler Copy = %d; want %d", n, size)
4232 }
4233 pw.Write([]byte("hi"))
4234 pw.Close()
4235 <-done
4236 }))
4237
4238 req, err := NewRequest("POST", cst.ts.URL, io.LimitReader(neverEnding('a'), size))
4239 if err != nil {
4240 t.Fatal(err)
4241 }
4242 res, err := cst.c.Do(req)
4243 if err != nil {
4244 t.Fatal(err)
4245 }
4246 all, err := io.ReadAll(res.Body)
4247 if err != nil {
4248 t.Fatal(err)
4249 }
4250 res.Body.Close()
4251 if string(all) != "hi" {
4252 t.Errorf("Body = %q; want hi", all)
4253 }
4254 }
4255
4256
4257 func TestCodesPreventingContentTypeAndBody(t *testing.T) {
4258 for _, code := range []int{StatusNotModified, StatusNoContent} {
4259 ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
4260 if r.URL.Path == "/header" {
4261 w.Header().Set("Content-Length", "123")
4262 }
4263 w.WriteHeader(code)
4264 if r.URL.Path == "/more" {
4265 w.Write([]byte("stuff"))
4266 }
4267 }))
4268 for _, req := range []string{
4269 "GET / HTTP/1.0",
4270 "GET /header HTTP/1.0",
4271 "GET /more HTTP/1.0",
4272 "GET / HTTP/1.1\nHost: foo",
4273 "GET /header HTTP/1.1\nHost: foo",
4274 "GET /more HTTP/1.1\nHost: foo",
4275 } {
4276 got := ht.rawResponse(req)
4277 wantStatus := fmt.Sprintf("%d %s", code, StatusText(code))
4278 if !strings.Contains(got, wantStatus) {
4279 t.Errorf("Code %d: Wanted %q Modified for %q: %s", code, wantStatus, req, got)
4280 } else if strings.Contains(got, "Content-Length") {
4281 t.Errorf("Code %d: Got a Content-Length from %q: %s", code, req, got)
4282 } else if strings.Contains(got, "stuff") {
4283 t.Errorf("Code %d: Response contains a body from %q: %s", code, req, got)
4284 }
4285 }
4286 }
4287 }
4288
4289 func TestContentTypeOkayOn204(t *testing.T) {
4290 ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
4291 w.Header().Set("Content-Length", "123")
4292 w.Header().Set("Content-Type", "foo/bar")
4293 w.WriteHeader(204)
4294 }))
4295 got := ht.rawResponse("GET / HTTP/1.1\nHost: foo")
4296 if !strings.Contains(got, "Content-Type: foo/bar") {
4297 t.Errorf("Response = %q; want Content-Type: foo/bar", got)
4298 }
4299 if strings.Contains(got, "Content-Length: 123") {
4300 t.Errorf("Response = %q; don't want a Content-Length", got)
4301 }
4302 }
4303
4304
4305
4306
4307
4308
4309
4310 func TestTransportAndServerSharedBodyRace(t *testing.T) {
4311 run(t, testTransportAndServerSharedBodyRace, testNotParallel)
4312 }
4313 func testTransportAndServerSharedBodyRace(t *testing.T, mode testMode) {
4314
4315
4316
4317
4318 runTimeSensitiveTest(t, []time.Duration{
4319 1 * time.Millisecond,
4320 5 * time.Millisecond,
4321 10 * time.Millisecond,
4322 50 * time.Millisecond,
4323 100 * time.Millisecond,
4324 500 * time.Millisecond,
4325 time.Second,
4326 5 * time.Second,
4327 }, func(t *testing.T, timeout time.Duration) error {
4328 SetRSTAvoidanceDelay(t, timeout)
4329 t.Logf("set RST avoidance delay to %v", timeout)
4330
4331 const bodySize = 1 << 20
4332
4333 var wg sync.WaitGroup
4334 backend := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
4335
4336
4337
4338
4339
4340
4341
4342
4343 wg.Add(1)
4344 defer wg.Done()
4345
4346 n, err := io.CopyN(rw, req.Body, bodySize)
4347 t.Logf("backend CopyN: %v, %v", n, err)
4348 <-req.Context().Done()
4349 }))
4350
4351
4352 defer func() {
4353 wg.Wait()
4354 backend.close()
4355 }()
4356
4357 var proxy *clientServerTest
4358 proxy = newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
4359 req2, _ := NewRequest("POST", backend.ts.URL, req.Body)
4360 req2.ContentLength = bodySize
4361 cancel := make(chan struct{})
4362 req2.Cancel = cancel
4363
4364 bresp, err := proxy.c.Do(req2)
4365 if err != nil {
4366 t.Errorf("Proxy outbound request: %v", err)
4367 return
4368 }
4369 _, err = io.CopyN(io.Discard, bresp.Body, bodySize/2)
4370 if err != nil {
4371 t.Errorf("Proxy copy error: %v", err)
4372 return
4373 }
4374 t.Cleanup(func() { bresp.Body.Close() })
4375
4376
4377
4378
4379
4380
4381 if mode == http2Mode {
4382 close(cancel)
4383 } else {
4384 proxy.c.Transport.(*Transport).CancelRequest(req2)
4385 }
4386 rw.Write([]byte("OK"))
4387 }))
4388 defer proxy.close()
4389
4390 req, _ := NewRequest("POST", proxy.ts.URL, io.LimitReader(neverEnding('a'), bodySize))
4391 res, err := proxy.c.Do(req)
4392 if err != nil {
4393 return fmt.Errorf("original request: %v", err)
4394 }
4395 res.Body.Close()
4396 return nil
4397 })
4398 }
4399
4400
4401
4402
4403 func TestRequestBodyCloseDoesntBlock(t *testing.T) {
4404 run(t, testRequestBodyCloseDoesntBlock, []testMode{http1Mode})
4405 }
4406 func testRequestBodyCloseDoesntBlock(t *testing.T, mode testMode) {
4407 if testing.Short() {
4408 t.Skip("skipping in -short mode")
4409 }
4410
4411 readErrCh := make(chan error, 1)
4412 errCh := make(chan error, 2)
4413
4414 server := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
4415 go func(body io.Reader) {
4416 _, err := body.Read(make([]byte, 100))
4417 readErrCh <- err
4418 }(req.Body)
4419 time.Sleep(500 * time.Millisecond)
4420 })).ts
4421
4422 closeConn := make(chan bool)
4423 defer close(closeConn)
4424 go func() {
4425 conn, err := net.Dial("tcp", server.Listener.Addr().String())
4426 if err != nil {
4427 errCh <- err
4428 return
4429 }
4430 defer conn.Close()
4431 _, err = conn.Write([]byte("POST / HTTP/1.1\r\nConnection: close\r\nHost: foo\r\nContent-Length: 100000\r\n\r\n"))
4432 if err != nil {
4433 errCh <- err
4434 return
4435 }
4436
4437
4438 <-closeConn
4439 }()
4440 select {
4441 case err := <-readErrCh:
4442 if err == nil {
4443 t.Error("Read was nil. Expected error.")
4444 }
4445 case err := <-errCh:
4446 t.Error(err)
4447 }
4448 }
4449
4450
4451 func TestResponseWriterWriteString(t *testing.T) {
4452 okc := make(chan bool, 1)
4453 ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
4454 _, ok := w.(io.StringWriter)
4455 okc <- ok
4456 }))
4457 ht.rawResponse("GET / HTTP/1.0")
4458 select {
4459 case ok := <-okc:
4460 if !ok {
4461 t.Error("ResponseWriter did not implement io.StringWriter")
4462 }
4463 default:
4464 t.Error("handler was never called")
4465 }
4466 }
4467
4468 func TestServerConnState(t *testing.T) { run(t, testServerConnState, []testMode{http1Mode}) }
4469 func testServerConnState(t *testing.T, mode testMode) {
4470 handler := map[string]func(w ResponseWriter, r *Request){
4471 "/": func(w ResponseWriter, r *Request) {
4472 fmt.Fprintf(w, "Hello.")
4473 },
4474 "/close": func(w ResponseWriter, r *Request) {
4475 w.Header().Set("Connection", "close")
4476 fmt.Fprintf(w, "Hello.")
4477 },
4478 "/hijack": func(w ResponseWriter, r *Request) {
4479 c, _, _ := w.(Hijacker).Hijack()
4480 c.Write([]byte("HTTP/1.0 200 OK\r\nConnection: close\r\n\r\nHello."))
4481 c.Close()
4482 },
4483 "/hijack-panic": func(w ResponseWriter, r *Request) {
4484 c, _, _ := w.(Hijacker).Hijack()
4485 c.Write([]byte("HTTP/1.0 200 OK\r\nConnection: close\r\n\r\nHello."))
4486 c.Close()
4487 panic("intentional panic")
4488 },
4489 }
4490
4491
4492 type stateLog struct {
4493 active net.Conn
4494 got []ConnState
4495 want []ConnState
4496 complete chan<- struct{}
4497 }
4498 activeLog := make(chan *stateLog, 1)
4499
4500
4501
4502
4503 wantLog := func(doRequests func(), want ...ConnState) {
4504 t.Helper()
4505 complete := make(chan struct{})
4506 activeLog <- &stateLog{want: want, complete: complete}
4507
4508 doRequests()
4509
4510 <-complete
4511 sl := <-activeLog
4512 if !slices.Equal(sl.got, sl.want) {
4513 t.Errorf("Request(s) produced unexpected state sequence.\nGot: %v\nWant: %v", sl.got, sl.want)
4514 }
4515
4516
4517
4518 }
4519
4520 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
4521 handler[r.URL.Path](w, r)
4522 }), func(ts *httptest.Server) {
4523 ts.Config.ErrorLog = log.New(io.Discard, "", 0)
4524 ts.Config.ConnState = func(c net.Conn, state ConnState) {
4525 if c == nil {
4526 t.Errorf("nil conn seen in state %s", state)
4527 return
4528 }
4529 sl := <-activeLog
4530 if sl.active == nil && state == StateNew {
4531 sl.active = c
4532 } else if sl.active != c {
4533 t.Errorf("unexpected conn in state %s", state)
4534 activeLog <- sl
4535 return
4536 }
4537 sl.got = append(sl.got, state)
4538 if sl.complete != nil && (len(sl.got) >= len(sl.want) || !slices.Equal(sl.got, sl.want[:len(sl.got)])) {
4539 close(sl.complete)
4540 sl.complete = nil
4541 }
4542 activeLog <- sl
4543 }
4544 }).ts
4545 defer func() {
4546 activeLog <- &stateLog{}
4547 ts.Close()
4548 }()
4549
4550 c := ts.Client()
4551
4552 mustGet := func(url string, headers ...string) {
4553 t.Helper()
4554 req, err := NewRequest("GET", url, nil)
4555 if err != nil {
4556 t.Fatal(err)
4557 }
4558 for len(headers) > 0 {
4559 req.Header.Add(headers[0], headers[1])
4560 headers = headers[2:]
4561 }
4562 res, err := c.Do(req)
4563 if err != nil {
4564 t.Errorf("Error fetching %s: %v", url, err)
4565 return
4566 }
4567 _, err = io.ReadAll(res.Body)
4568 defer res.Body.Close()
4569 if err != nil {
4570 t.Errorf("Error reading %s: %v", url, err)
4571 }
4572 }
4573
4574 wantLog(func() {
4575 mustGet(ts.URL + "/")
4576 mustGet(ts.URL + "/close")
4577 }, StateNew, StateActive, StateIdle, StateActive, StateClosed)
4578
4579 wantLog(func() {
4580 mustGet(ts.URL + "/")
4581 mustGet(ts.URL+"/", "Connection", "close")
4582 }, StateNew, StateActive, StateIdle, StateActive, StateClosed)
4583
4584 wantLog(func() {
4585 mustGet(ts.URL + "/hijack")
4586 }, StateNew, StateActive, StateHijacked)
4587
4588 wantLog(func() {
4589 mustGet(ts.URL + "/hijack-panic")
4590 }, StateNew, StateActive, StateHijacked)
4591
4592 wantLog(func() {
4593 c, err := net.Dial("tcp", ts.Listener.Addr().String())
4594 if err != nil {
4595 t.Fatal(err)
4596 }
4597 c.Close()
4598 }, StateNew, StateClosed)
4599
4600 wantLog(func() {
4601 c, err := net.Dial("tcp", ts.Listener.Addr().String())
4602 if err != nil {
4603 t.Fatal(err)
4604 }
4605 if _, err := io.WriteString(c, "BOGUS REQUEST\r\n\r\n"); err != nil {
4606 t.Fatal(err)
4607 }
4608 c.Read(make([]byte, 1))
4609 c.Close()
4610 }, StateNew, StateActive, StateClosed)
4611
4612 wantLog(func() {
4613 c, err := net.Dial("tcp", ts.Listener.Addr().String())
4614 if err != nil {
4615 t.Fatal(err)
4616 }
4617 if _, err := io.WriteString(c, "GET / HTTP/1.1\r\nHost: foo\r\n\r\n"); err != nil {
4618 t.Fatal(err)
4619 }
4620 res, err := ReadResponse(bufio.NewReader(c), nil)
4621 if err != nil {
4622 t.Fatal(err)
4623 }
4624 if _, err := io.Copy(io.Discard, res.Body); err != nil {
4625 t.Fatal(err)
4626 }
4627 c.Close()
4628 }, StateNew, StateActive, StateIdle, StateClosed)
4629 }
4630
4631 func TestServerKeepAlivesEnabledResultClose(t *testing.T) {
4632 run(t, testServerKeepAlivesEnabledResultClose, []testMode{http1Mode})
4633 }
4634 func testServerKeepAlivesEnabledResultClose(t *testing.T, mode testMode) {
4635 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
4636 }), func(ts *httptest.Server) {
4637 ts.Config.SetKeepAlivesEnabled(false)
4638 }).ts
4639 res, err := ts.Client().Get(ts.URL)
4640 if err != nil {
4641 t.Fatal(err)
4642 }
4643 defer res.Body.Close()
4644 if !res.Close {
4645 t.Errorf("Body.Close == false; want true")
4646 }
4647 }
4648
4649
4650 func TestServerEmptyBodyRace(t *testing.T) { run(t, testServerEmptyBodyRace) }
4651 func testServerEmptyBodyRace(t *testing.T, mode testMode) {
4652 var n int32
4653 cst := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
4654 atomic.AddInt32(&n, 1)
4655 }), optQuietLog)
4656 var wg sync.WaitGroup
4657 const reqs = 20
4658 for i := 0; i < reqs; i++ {
4659 wg.Add(1)
4660 go func() {
4661 defer wg.Done()
4662 res, err := cst.c.Get(cst.ts.URL)
4663 if err != nil {
4664
4665
4666 time.Sleep(10 * time.Millisecond)
4667 res, err = cst.c.Get(cst.ts.URL)
4668 if err != nil {
4669 t.Error(err)
4670 return
4671 }
4672 }
4673 defer res.Body.Close()
4674 _, err = io.Copy(io.Discard, res.Body)
4675 if err != nil {
4676 t.Error(err)
4677 return
4678 }
4679 }()
4680 }
4681 wg.Wait()
4682 if got := atomic.LoadInt32(&n); got != reqs {
4683 t.Errorf("handler ran %d times; want %d", got, reqs)
4684 }
4685 }
4686
4687 func TestServerConnStateNew(t *testing.T) {
4688 sawNew := false
4689 srv := &Server{
4690 ConnState: func(c net.Conn, state ConnState) {
4691 if state == StateNew {
4692 sawNew = true
4693 }
4694 },
4695 Handler: HandlerFunc(func(w ResponseWriter, r *Request) {}),
4696 }
4697 srv.Serve(&oneConnListener{
4698 conn: &rwTestConn{
4699 Reader: strings.NewReader("GET / HTTP/1.1\r\nHost: foo\r\n\r\n"),
4700 Writer: io.Discard,
4701 },
4702 })
4703 if !sawNew {
4704 t.Error("StateNew not seen")
4705 }
4706 }
4707
4708 type closeWriteTestConn struct {
4709 rwTestConn
4710 didCloseWrite bool
4711 }
4712
4713 func (c *closeWriteTestConn) CloseWrite() error {
4714 c.didCloseWrite = true
4715 return nil
4716 }
4717
4718 func TestCloseWrite(t *testing.T) {
4719 SetRSTAvoidanceDelay(t, 1*time.Millisecond)
4720
4721 var srv Server
4722 var testConn closeWriteTestConn
4723 c := ExportServerNewConn(&srv, &testConn)
4724 ExportCloseWriteAndWait(c)
4725 if !testConn.didCloseWrite {
4726 t.Error("didn't see CloseWrite call")
4727 }
4728 }
4729
4730
4731
4732
4733
4734
4735
4736
4737 func TestServerFlushAndHijack(t *testing.T) { run(t, testServerFlushAndHijack, []testMode{http1Mode}) }
4738 func testServerFlushAndHijack(t *testing.T, mode testMode) {
4739 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
4740 io.WriteString(w, "Hello, ")
4741 w.(Flusher).Flush()
4742 conn, buf, _ := w.(Hijacker).Hijack()
4743 buf.WriteString("6\r\nworld!\r\n0\r\n\r\n")
4744 if err := buf.Flush(); err != nil {
4745 t.Error(err)
4746 }
4747 if err := conn.Close(); err != nil {
4748 t.Error(err)
4749 }
4750 })).ts
4751 res, err := Get(ts.URL)
4752 if err != nil {
4753 t.Fatal(err)
4754 }
4755 defer res.Body.Close()
4756 all, err := io.ReadAll(res.Body)
4757 if err != nil {
4758 t.Fatal(err)
4759 }
4760 if want := "Hello, world!"; string(all) != want {
4761 t.Errorf("Got %q; want %q", all, want)
4762 }
4763 }
4764
4765
4766
4767
4768
4769
4770
4771 func TestServerKeepAliveAfterWriteError(t *testing.T) {
4772 run(t, testServerKeepAliveAfterWriteError, []testMode{http1Mode})
4773 }
4774 func testServerKeepAliveAfterWriteError(t *testing.T, mode testMode) {
4775 if testing.Short() {
4776 t.Skip("skipping in -short mode")
4777 }
4778 const numReq = 3
4779 addrc := make(chan string, numReq)
4780 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
4781 addrc <- r.RemoteAddr
4782 time.Sleep(500 * time.Millisecond)
4783 w.(Flusher).Flush()
4784 }), func(ts *httptest.Server) {
4785 ts.Config.WriteTimeout = 250 * time.Millisecond
4786 }).ts
4787
4788 errc := make(chan error, numReq)
4789 go func() {
4790 defer close(errc)
4791 for i := 0; i < numReq; i++ {
4792 res, err := Get(ts.URL)
4793 if res != nil {
4794 res.Body.Close()
4795 }
4796 errc <- err
4797 }
4798 }()
4799
4800 addrSeen := map[string]bool{}
4801 numOkay := 0
4802 for {
4803 select {
4804 case v := <-addrc:
4805 addrSeen[v] = true
4806 case err, ok := <-errc:
4807 if !ok {
4808 if len(addrSeen) != numReq {
4809 t.Errorf("saw %d unique client addresses; want %d", len(addrSeen), numReq)
4810 }
4811 if numOkay != 0 {
4812 t.Errorf("got %d successful client requests; want 0", numOkay)
4813 }
4814 return
4815 }
4816 if err == nil {
4817 numOkay++
4818 }
4819 }
4820 }
4821 }
4822
4823
4824
4825 func TestNoContentLengthIfTransferEncoding(t *testing.T) {
4826 run(t, testNoContentLengthIfTransferEncoding, []testMode{http1Mode})
4827 }
4828 func testNoContentLengthIfTransferEncoding(t *testing.T, mode testMode) {
4829 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
4830 w.Header().Set("Transfer-Encoding", "foo")
4831 io.WriteString(w, "<html>")
4832 })).ts
4833 c, err := net.Dial("tcp", ts.Listener.Addr().String())
4834 if err != nil {
4835 t.Fatalf("Dial: %v", err)
4836 }
4837 defer c.Close()
4838 if _, err := io.WriteString(c, "GET / HTTP/1.1\r\nHost: foo\r\n\r\n"); err != nil {
4839 t.Fatal(err)
4840 }
4841 bs := bufio.NewScanner(c)
4842 var got strings.Builder
4843 for bs.Scan() {
4844 if strings.TrimSpace(bs.Text()) == "" {
4845 break
4846 }
4847 got.WriteString(bs.Text())
4848 got.WriteByte('\n')
4849 }
4850 if err := bs.Err(); err != nil {
4851 t.Fatal(err)
4852 }
4853 if strings.Contains(got.String(), "Content-Length") {
4854 t.Errorf("Unexpected Content-Length in response headers: %s", got.String())
4855 }
4856 if strings.Contains(got.String(), "Content-Type") {
4857 t.Errorf("Unexpected Content-Type in response headers: %s", got.String())
4858 }
4859 }
4860
4861
4862
4863 func TestTolerateCRLFBeforeRequestLine(t *testing.T) {
4864 req := []byte("POST / HTTP/1.1\r\nHost: golang.org\r\nContent-Length: 3\r\n\r\nABC" +
4865 "\r\n\r\n" +
4866 "GET / HTTP/1.1\r\nHost: golang.org\r\n\r\n")
4867 var buf bytes.Buffer
4868 conn := &rwTestConn{
4869 Reader: bytes.NewReader(req),
4870 Writer: &buf,
4871 closec: make(chan bool, 1),
4872 }
4873 ln := &oneConnListener{conn: conn}
4874 numReq := 0
4875 go Serve(ln, HandlerFunc(func(rw ResponseWriter, r *Request) {
4876 numReq++
4877 }))
4878 <-conn.closec
4879 if numReq != 2 {
4880 t.Errorf("num requests = %d; want 2", numReq)
4881 t.Logf("Res: %s", buf.Bytes())
4882 }
4883 }
4884
4885 func TestIssue13893_Expect100(t *testing.T) {
4886
4887 req := reqBytes(`PUT /readbody HTTP/1.1
4888 User-Agent: PycURL/7.22.0
4889 Host: 127.0.0.1:9000
4890 Accept: */*
4891 Expect: 100-continue
4892 Content-Length: 10
4893
4894 HelloWorld
4895
4896 `)
4897 var buf bytes.Buffer
4898 conn := &rwTestConn{
4899 Reader: bytes.NewReader(req),
4900 Writer: &buf,
4901 closec: make(chan bool, 1),
4902 }
4903 ln := &oneConnListener{conn: conn}
4904 go Serve(ln, HandlerFunc(func(w ResponseWriter, r *Request) {
4905 if _, ok := r.Header["Expect"]; !ok {
4906 t.Error("Expect header should not be filtered out")
4907 }
4908 }))
4909 <-conn.closec
4910 }
4911
4912 func TestIssue11549_Expect100(t *testing.T) {
4913 req := reqBytes(`PUT /readbody HTTP/1.1
4914 User-Agent: PycURL/7.22.0
4915 Host: 127.0.0.1:9000
4916 Accept: */*
4917 Expect: 100-continue
4918 Content-Length: 10
4919
4920 HelloWorldPUT /noreadbody HTTP/1.1
4921 User-Agent: PycURL/7.22.0
4922 Host: 127.0.0.1:9000
4923 Accept: */*
4924 Expect: 100-continue
4925 Content-Length: 10
4926
4927 GET /should-be-ignored HTTP/1.1
4928 Host: foo
4929
4930 `)
4931 var buf strings.Builder
4932 conn := &rwTestConn{
4933 Reader: bytes.NewReader(req),
4934 Writer: &buf,
4935 closec: make(chan bool, 1),
4936 }
4937 ln := &oneConnListener{conn: conn}
4938 numReq := 0
4939 go Serve(ln, HandlerFunc(func(w ResponseWriter, r *Request) {
4940 numReq++
4941 if r.URL.Path == "/readbody" {
4942 io.ReadAll(r.Body)
4943 }
4944 io.WriteString(w, "Hello world!")
4945 }))
4946 <-conn.closec
4947 if numReq != 2 {
4948 t.Errorf("num requests = %d; want 2", numReq)
4949 }
4950 if !strings.Contains(buf.String(), "Connection: close\r\n") {
4951 t.Errorf("expected 'Connection: close' in response; got: %s", buf.String())
4952 }
4953 }
4954
4955
4956
4957 func TestHandlerFinishSkipBigContentLengthRead(t *testing.T) {
4958 setParallel(t)
4959 conn := newTestConn()
4960 conn.readBuf.WriteString(
4961 "POST / HTTP/1.1\r\n" +
4962 "Host: test\r\n" +
4963 "Content-Length: 9999999999\r\n" +
4964 "\r\n" + strings.Repeat("a", 1<<20))
4965
4966 ls := &oneConnListener{conn}
4967 var inHandlerLen int
4968 go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
4969 inHandlerLen = conn.readBuf.Len()
4970 rw.WriteHeader(404)
4971 }))
4972 <-conn.closec
4973 afterHandlerLen := conn.readBuf.Len()
4974
4975 if afterHandlerLen != inHandlerLen {
4976 t.Errorf("unexpected implicit read. Read buffer went from %d -> %d", inHandlerLen, afterHandlerLen)
4977 }
4978 }
4979
4980 func TestHandlerSetsBodyNil(t *testing.T) { run(t, testHandlerSetsBodyNil) }
4981 func testHandlerSetsBodyNil(t *testing.T, mode testMode) {
4982 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
4983 r.Body = nil
4984 fmt.Fprintf(w, "%v", r.RemoteAddr)
4985 }))
4986 get := func() string {
4987 res, err := cst.c.Get(cst.ts.URL)
4988 if err != nil {
4989 t.Fatal(err)
4990 }
4991 defer res.Body.Close()
4992 slurp, err := io.ReadAll(res.Body)
4993 if err != nil {
4994 t.Fatal(err)
4995 }
4996 return string(slurp)
4997 }
4998 a, b := get(), get()
4999 if a != b {
5000 t.Errorf("Failed to reuse connections between requests: %v vs %v", a, b)
5001 }
5002 }
5003
5004
5005
5006 func TestServerValidatesHostHeader(t *testing.T) {
5007 tests := []struct {
5008 proto string
5009 host string
5010 want int
5011 }{
5012 {"HTTP/0.9", "", 505},
5013
5014 {"HTTP/1.1", "", 400},
5015 {"HTTP/1.1", "Host: \r\n", 200},
5016 {"HTTP/1.1", "Host: 1.2.3.4\r\n", 200},
5017 {"HTTP/1.1", "Host: foo.com\r\n", 200},
5018 {"HTTP/1.1", "Host: foo-bar_baz.com\r\n", 200},
5019 {"HTTP/1.1", "Host: foo.com:80\r\n", 200},
5020 {"HTTP/1.1", "Host: ::1\r\n", 200},
5021 {"HTTP/1.1", "Host: [::1]\r\n", 200},
5022 {"HTTP/1.1", "Host: [::1]:80\r\n", 200},
5023 {"HTTP/1.1", "Host: [::1%25en0]:80\r\n", 200},
5024 {"HTTP/1.1", "Host: 1.2.3.4\r\n", 200},
5025 {"HTTP/1.1", "Host: \x06\r\n", 400},
5026 {"HTTP/1.1", "Host: \xff\r\n", 400},
5027 {"HTTP/1.1", "Host: {\r\n", 400},
5028 {"HTTP/1.1", "Host: }\r\n", 400},
5029 {"HTTP/1.1", "Host: first\r\nHost: second\r\n", 400},
5030
5031
5032
5033 {"HTTP/1.0", "", 200},
5034 {"HTTP/1.0", "Host: first\r\nHost: second\r\n", 400},
5035 {"HTTP/1.0", "Host: \xff\r\n", 400},
5036
5037
5038 {"PRI * HTTP/2.0", "", 200},
5039
5040
5041 {"CONNECT golang.org:443 HTTP/1.1", "", 200},
5042
5043
5044 {"PRI / HTTP/2.0", "", 505},
5045 {"GET / HTTP/2.0", "", 505},
5046 {"GET / HTTP/3.0", "", 505},
5047 }
5048 for _, tt := range tests {
5049 conn := newTestConn()
5050 methodTarget := "GET / "
5051 if !strings.HasPrefix(tt.proto, "HTTP/") {
5052 methodTarget = ""
5053 }
5054 io.WriteString(&conn.readBuf, methodTarget+tt.proto+"\r\n"+tt.host+"\r\n")
5055
5056 ln := &oneConnListener{conn}
5057 srv := Server{
5058 ErrorLog: quietLog,
5059 Handler: HandlerFunc(func(ResponseWriter, *Request) {}),
5060 }
5061 go srv.Serve(ln)
5062 <-conn.closec
5063 res, err := ReadResponse(bufio.NewReader(&conn.writeBuf), nil)
5064 if err != nil {
5065 t.Errorf("For %s %q, ReadResponse: %v", tt.proto, tt.host, res)
5066 continue
5067 }
5068 if res.StatusCode != tt.want {
5069 t.Errorf("For %s %q, Status = %d; want %d", tt.proto, tt.host, res.StatusCode, tt.want)
5070 }
5071 }
5072 }
5073
5074 func TestServerHandlersCanHandleH2PRI(t *testing.T) {
5075 run(t, testServerHandlersCanHandleH2PRI, []testMode{http1Mode})
5076 }
5077 func testServerHandlersCanHandleH2PRI(t *testing.T, mode testMode) {
5078 const upgradeResponse = "upgrade here"
5079 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
5080 conn, br, err := w.(Hijacker).Hijack()
5081 if err != nil {
5082 t.Error(err)
5083 return
5084 }
5085 defer conn.Close()
5086 if r.Method != "PRI" || r.RequestURI != "*" {
5087 t.Errorf("Got method/target %q %q; want PRI *", r.Method, r.RequestURI)
5088 return
5089 }
5090 if !r.Close {
5091 t.Errorf("Request.Close = true; want false")
5092 }
5093 const want = "SM\r\n\r\n"
5094 buf := make([]byte, len(want))
5095 n, err := io.ReadFull(br, buf)
5096 if err != nil || string(buf[:n]) != want {
5097 t.Errorf("Read = %v, %v (%q), want %q", n, err, buf[:n], want)
5098 return
5099 }
5100 io.WriteString(conn, upgradeResponse)
5101 })).ts
5102
5103 c, err := net.Dial("tcp", ts.Listener.Addr().String())
5104 if err != nil {
5105 t.Fatalf("Dial: %v", err)
5106 }
5107 defer c.Close()
5108 io.WriteString(c, "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n")
5109 slurp, err := io.ReadAll(c)
5110 if err != nil {
5111 t.Fatal(err)
5112 }
5113 if string(slurp) != upgradeResponse {
5114 t.Errorf("Handler response = %q; want %q", slurp, upgradeResponse)
5115 }
5116 }
5117
5118
5119
5120 func TestServerValidatesHeaders(t *testing.T) {
5121 setParallel(t)
5122 tests := []struct {
5123 header string
5124 want int
5125 }{
5126 {"", 200},
5127 {"Foo: bar\r\n", 200},
5128 {"X-Foo: bar\r\n", 200},
5129 {"Foo: a space\r\n", 200},
5130
5131 {"A space: foo\r\n", 400},
5132 {"foo\xffbar: foo\r\n", 400},
5133 {"foo\x00bar: foo\r\n", 400},
5134 {"Foo: " + strings.Repeat("x", 1<<21) + "\r\n", 431},
5135
5136
5137 {"Foo : bar\r\n", 400},
5138 {"Foo\t: bar\r\n", 400},
5139
5140
5141
5142 {": empty key\r\n", 400},
5143
5144
5145
5146
5147 {"Content-Length: notdigits\r\n", 400},
5148 {"Content-Length: notdigits\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\n", 400},
5149
5150 {"foo: foo foo\r\n", 200},
5151 {"foo: foo\tfoo\r\n", 200},
5152 {"foo: foo\x00foo\r\n", 400},
5153 {"foo: foo\x7ffoo\r\n", 400},
5154 {"foo: foo\xfffoo\r\n", 200},
5155 }
5156 for _, tt := range tests {
5157 conn := newTestConn()
5158 io.WriteString(&conn.readBuf, "GET / HTTP/1.1\r\nHost: foo\r\n"+tt.header+"\r\n")
5159
5160 ln := &oneConnListener{conn}
5161 srv := Server{
5162 ErrorLog: quietLog,
5163 Handler: HandlerFunc(func(ResponseWriter, *Request) {}),
5164 }
5165 go srv.Serve(ln)
5166 <-conn.closec
5167 res, err := ReadResponse(bufio.NewReader(&conn.writeBuf), nil)
5168 if err != nil {
5169 t.Errorf("For %q, ReadResponse: %v", tt.header, res)
5170 continue
5171 }
5172 if res.StatusCode != tt.want {
5173 t.Errorf("For %q, Status = %d; want %d", tt.header, res.StatusCode, tt.want)
5174 }
5175 }
5176 }
5177
5178 func TestServerRequestContextCancel_ServeHTTPDone(t *testing.T) {
5179 run(t, testServerRequestContextCancel_ServeHTTPDone)
5180 }
5181 func testServerRequestContextCancel_ServeHTTPDone(t *testing.T, mode testMode) {
5182 ctxc := make(chan context.Context, 1)
5183 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
5184 ctx := r.Context()
5185 select {
5186 case <-ctx.Done():
5187 t.Error("should not be Done in ServeHTTP")
5188 default:
5189 }
5190 ctxc <- ctx
5191 }))
5192 res, err := cst.c.Get(cst.ts.URL)
5193 if err != nil {
5194 t.Fatal(err)
5195 }
5196 res.Body.Close()
5197 ctx := <-ctxc
5198 select {
5199 case <-ctx.Done():
5200 default:
5201 t.Error("context should be done after ServeHTTP completes")
5202 }
5203 }
5204
5205
5206
5207
5208
5209 func TestServerRequestContextCancel_ConnClose(t *testing.T) {
5210 run(t, testServerRequestContextCancel_ConnClose, []testMode{http1Mode})
5211 }
5212 func testServerRequestContextCancel_ConnClose(t *testing.T, mode testMode) {
5213 inHandler := make(chan struct{})
5214 handlerDone := make(chan struct{})
5215 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
5216 close(inHandler)
5217 <-r.Context().Done()
5218 close(handlerDone)
5219 })).ts
5220 c, err := net.Dial("tcp", ts.Listener.Addr().String())
5221 if err != nil {
5222 t.Fatal(err)
5223 }
5224 defer c.Close()
5225 io.WriteString(c, "GET / HTTP/1.1\r\nHost: foo\r\n\r\n")
5226 <-inHandler
5227 c.Close()
5228 <-handlerDone
5229 }
5230
5231 func TestServerContext_ServerContextKey(t *testing.T) {
5232 run(t, testServerContext_ServerContextKey)
5233 }
5234 func testServerContext_ServerContextKey(t *testing.T, mode testMode) {
5235 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
5236 ctx := r.Context()
5237 got := ctx.Value(ServerContextKey)
5238 if _, ok := got.(*Server); !ok {
5239 t.Errorf("context value = %T; want *http.Server", got)
5240 }
5241 }))
5242 res, err := cst.c.Get(cst.ts.URL)
5243 if err != nil {
5244 t.Fatal(err)
5245 }
5246 res.Body.Close()
5247 }
5248
5249 func TestServerContext_LocalAddrContextKey(t *testing.T) {
5250 run(t, testServerContext_LocalAddrContextKey)
5251 }
5252 func testServerContext_LocalAddrContextKey(t *testing.T, mode testMode) {
5253 ch := make(chan any, 1)
5254 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
5255 ch <- r.Context().Value(LocalAddrContextKey)
5256 }))
5257 if _, err := cst.c.Head(cst.ts.URL); err != nil {
5258 t.Fatal(err)
5259 }
5260
5261 host := cst.ts.Listener.Addr().String()
5262 got := <-ch
5263 if addr, ok := got.(net.Addr); !ok {
5264 t.Errorf("local addr value = %T; want net.Addr", got)
5265 } else if fmt.Sprint(addr) != host {
5266 t.Errorf("local addr = %v; want %v", addr, host)
5267 }
5268 }
5269
5270
5271 func TestHandlerSetTransferEncodingChunked(t *testing.T) {
5272 setParallel(t)
5273 defer afterTest(t)
5274 ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
5275 w.Header().Set("Transfer-Encoding", "chunked")
5276 w.Write([]byte("hello"))
5277 }))
5278 resp := ht.rawResponse("GET / HTTP/1.1\nHost: foo")
5279 const hdr = "Transfer-Encoding: chunked"
5280 if n := strings.Count(resp, hdr); n != 1 {
5281 t.Errorf("want 1 occurrence of %q in response, got %v\nresponse: %v", hdr, n, resp)
5282 }
5283 }
5284
5285
5286 func TestHandlerSetTransferEncodingGzip(t *testing.T) {
5287 setParallel(t)
5288 defer afterTest(t)
5289 ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
5290 w.Header().Set("Transfer-Encoding", "gzip")
5291 gz := gzip.NewWriter(w)
5292 gz.Write([]byte("hello"))
5293 gz.Close()
5294 }))
5295 resp := ht.rawResponse("GET / HTTP/1.1\nHost: foo")
5296 for _, v := range []string{"gzip", "chunked"} {
5297 hdr := "Transfer-Encoding: " + v
5298 if n := strings.Count(resp, hdr); n != 1 {
5299 t.Errorf("want 1 occurrence of %q in response, got %v\nresponse: %v", hdr, n, resp)
5300 }
5301 }
5302 }
5303
5304 func BenchmarkClientServer(b *testing.B) {
5305 run(b, benchmarkClientServer, []testMode{http1Mode, https1Mode, http2Mode})
5306 }
5307 func benchmarkClientServer(b *testing.B, mode testMode) {
5308 b.ReportAllocs()
5309 b.StopTimer()
5310 ts := newClientServerTest(b, mode, HandlerFunc(func(rw ResponseWriter, r *Request) {
5311 fmt.Fprintf(rw, "Hello world.\n")
5312 })).ts
5313 b.StartTimer()
5314
5315 c := ts.Client()
5316 for i := 0; i < b.N; i++ {
5317 res, err := c.Get(ts.URL)
5318 if err != nil {
5319 b.Fatal("Get:", err)
5320 }
5321 all, err := io.ReadAll(res.Body)
5322 res.Body.Close()
5323 if err != nil {
5324 b.Fatal("ReadAll:", err)
5325 }
5326 body := string(all)
5327 if body != "Hello world.\n" {
5328 b.Fatal("Got body:", body)
5329 }
5330 }
5331
5332 b.StopTimer()
5333 }
5334
5335 func BenchmarkClientServerParallel(b *testing.B) {
5336 for _, parallelism := range []int{4, 64} {
5337 b.Run(fmt.Sprint(parallelism), func(b *testing.B) {
5338 run(b, func(b *testing.B, mode testMode) {
5339 benchmarkClientServerParallel(b, parallelism, mode)
5340 }, []testMode{http1Mode, https1Mode, http2Mode})
5341 })
5342 }
5343 }
5344
5345 func benchmarkClientServerParallel(b *testing.B, parallelism int, mode testMode) {
5346 b.ReportAllocs()
5347 ts := newClientServerTest(b, mode, HandlerFunc(func(rw ResponseWriter, r *Request) {
5348 fmt.Fprintf(rw, "Hello world.\n")
5349 })).ts
5350 b.ResetTimer()
5351 b.SetParallelism(parallelism)
5352 b.RunParallel(func(pb *testing.PB) {
5353 c := ts.Client()
5354 for pb.Next() {
5355 res, err := c.Get(ts.URL)
5356 if err != nil {
5357 b.Logf("Get: %v", err)
5358 continue
5359 }
5360 all, err := io.ReadAll(res.Body)
5361 res.Body.Close()
5362 if err != nil {
5363 b.Logf("ReadAll: %v", err)
5364 continue
5365 }
5366 body := string(all)
5367 if body != "Hello world.\n" {
5368 panic("Got body: " + body)
5369 }
5370 }
5371 })
5372 }
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383 func BenchmarkServer(b *testing.B) {
5384 b.ReportAllocs()
5385
5386 if url := os.Getenv("GO_TEST_BENCH_SERVER_URL"); url != "" {
5387 n, err := strconv.Atoi(os.Getenv("GO_TEST_BENCH_CLIENT_N"))
5388 if err != nil {
5389 panic(err)
5390 }
5391 for i := 0; i < n; i++ {
5392 res, err := Get(url)
5393 if err != nil {
5394 log.Panicf("Get: %v", err)
5395 }
5396 all, err := io.ReadAll(res.Body)
5397 res.Body.Close()
5398 if err != nil {
5399 log.Panicf("ReadAll: %v", err)
5400 }
5401 body := string(all)
5402 if body != "Hello world.\n" {
5403 log.Panicf("Got body: %q", body)
5404 }
5405 }
5406 os.Exit(0)
5407 return
5408 }
5409
5410 var res = []byte("Hello world.\n")
5411 b.StopTimer()
5412 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
5413 rw.Header().Set("Content-Type", "text/html; charset=utf-8")
5414 rw.Write(res)
5415 }))
5416 defer ts.Close()
5417 b.StartTimer()
5418
5419 cmd := testenv.Command(b, os.Args[0], "-test.run=^$", "-test.bench=^BenchmarkServer$")
5420 cmd.Env = append([]string{
5421 fmt.Sprintf("GO_TEST_BENCH_CLIENT_N=%d", b.N),
5422 fmt.Sprintf("GO_TEST_BENCH_SERVER_URL=%s", ts.URL),
5423 }, os.Environ()...)
5424 out, err := cmd.CombinedOutput()
5425 if err != nil {
5426 b.Errorf("Test failure: %v, with output: %s", err, out)
5427 }
5428 }
5429
5430
5431 func getNoBody(urlStr string) (*Response, error) {
5432 res, err := Get(urlStr)
5433 if err != nil {
5434 return nil, err
5435 }
5436 res.Body.Close()
5437 return res, nil
5438 }
5439
5440
5441
5442 func BenchmarkClient(b *testing.B) {
5443 var data = []byte("Hello world.\n")
5444
5445 url := startClientBenchmarkServer(b, HandlerFunc(func(w ResponseWriter, _ *Request) {
5446 w.Header().Set("Content-Type", "text/html; charset=utf-8")
5447 w.Write(data)
5448 }))
5449
5450
5451 b.StartTimer()
5452 for i := 0; i < b.N; i++ {
5453 res, err := Get(url)
5454 if err != nil {
5455 b.Fatalf("Get: %v", err)
5456 }
5457 body, err := io.ReadAll(res.Body)
5458 res.Body.Close()
5459 if err != nil {
5460 b.Fatalf("ReadAll: %v", err)
5461 }
5462 if !bytes.Equal(body, data) {
5463 b.Fatalf("Got body: %q", body)
5464 }
5465 }
5466 b.StopTimer()
5467 }
5468
5469 func startClientBenchmarkServer(b *testing.B, handler Handler) string {
5470 b.ReportAllocs()
5471 b.StopTimer()
5472
5473 if server := os.Getenv("GO_TEST_BENCH_SERVER"); server != "" {
5474
5475 port := os.Getenv("GO_TEST_BENCH_SERVER_PORT")
5476 if port == "" {
5477 port = "0"
5478 }
5479 ln, err := net.Listen("tcp", "localhost:"+port)
5480 if err != nil {
5481 log.Fatal(err)
5482 }
5483 fmt.Println(ln.Addr().String())
5484
5485 HandleFunc("/", func(w ResponseWriter, r *Request) {
5486 r.ParseForm()
5487 if r.Form.Get("stop") != "" {
5488 os.Exit(0)
5489 }
5490 handler.ServeHTTP(w, r)
5491 })
5492 var srv Server
5493 log.Fatal(srv.Serve(ln))
5494 }
5495
5496
5497 ctx, cancel := context.WithCancel(context.Background())
5498 cmd := testenv.CommandContext(b, ctx, os.Args[0], "-test.run=^$", "-test.bench=^"+b.Name()+"$")
5499 cmd.Env = append(cmd.Environ(), "GO_TEST_BENCH_SERVER=yes")
5500 cmd.Stderr = os.Stderr
5501 stdout, err := cmd.StdoutPipe()
5502 if err != nil {
5503 b.Fatal(err)
5504 }
5505 if err := cmd.Start(); err != nil {
5506 b.Fatalf("subprocess failed to start: %v", err)
5507 }
5508
5509 done := make(chan error, 1)
5510 go func() {
5511 done <- cmd.Wait()
5512 close(done)
5513 }()
5514
5515
5516
5517 bs := bufio.NewScanner(stdout)
5518 if !bs.Scan() {
5519 b.Fatalf("failed to read listening URL from child: %v", bs.Err())
5520 }
5521 url := "http://" + strings.TrimSpace(bs.Text()) + "/"
5522 if _, err := getNoBody(url); err != nil {
5523 b.Fatalf("initial probe of child process failed: %v", err)
5524 }
5525
5526
5527 b.Cleanup(func() {
5528 getNoBody(url + "?stop=yes")
5529 if err := <-done; err != nil {
5530 b.Fatalf("subprocess failed: %v", err)
5531 }
5532
5533 cancel()
5534 <-done
5535
5536 afterTest(b)
5537 })
5538
5539 return url
5540 }
5541
5542 func BenchmarkClientGzip(b *testing.B) {
5543 const responseSize = 1024 * 1024
5544
5545 var buf bytes.Buffer
5546 gz := gzip.NewWriter(&buf)
5547 if _, err := io.CopyN(gz, crand.Reader, responseSize); err != nil {
5548 b.Fatal(err)
5549 }
5550 gz.Close()
5551
5552 data := buf.Bytes()
5553
5554 url := startClientBenchmarkServer(b, HandlerFunc(func(w ResponseWriter, _ *Request) {
5555 w.Header().Set("Content-Encoding", "gzip")
5556 w.Write(data)
5557 }))
5558
5559
5560 b.StartTimer()
5561 for i := 0; i < b.N; i++ {
5562 res, err := Get(url)
5563 if err != nil {
5564 b.Fatalf("Get: %v", err)
5565 }
5566 n, err := io.Copy(io.Discard, res.Body)
5567 res.Body.Close()
5568 if err != nil {
5569 b.Fatalf("ReadAll: %v", err)
5570 }
5571 if n != responseSize {
5572 b.Fatalf("ReadAll: expected %d bytes, got %d", responseSize, n)
5573 }
5574 }
5575 b.StopTimer()
5576 }
5577
5578 func BenchmarkServerFakeConnNoKeepAlive(b *testing.B) {
5579 b.ReportAllocs()
5580 req := reqBytes(`GET / HTTP/1.0
5581 Host: golang.org
5582 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
5583 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17
5584 Accept-Encoding: gzip,deflate,sdch
5585 Accept-Language: en-US,en;q=0.8
5586 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
5587 `)
5588 res := []byte("Hello world!\n")
5589
5590 conn := newTestConn()
5591 handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
5592 rw.Header().Set("Content-Type", "text/html; charset=utf-8")
5593 rw.Write(res)
5594 })
5595 ln := new(oneConnListener)
5596 for i := 0; i < b.N; i++ {
5597 conn.readBuf.Reset()
5598 conn.writeBuf.Reset()
5599 conn.readBuf.Write(req)
5600 ln.conn = conn
5601 Serve(ln, handler)
5602 <-conn.closec
5603 }
5604 }
5605
5606
5607 type repeatReader struct {
5608 content []byte
5609 count int
5610 off int
5611 }
5612
5613 func (r *repeatReader) Read(p []byte) (n int, err error) {
5614 if r.count <= 0 {
5615 return 0, io.EOF
5616 }
5617 n = copy(p, r.content[r.off:])
5618 r.off += n
5619 if r.off == len(r.content) {
5620 r.count--
5621 r.off = 0
5622 }
5623 return
5624 }
5625
5626 func BenchmarkServerFakeConnWithKeepAlive(b *testing.B) {
5627 b.ReportAllocs()
5628
5629 req := reqBytes(`GET / HTTP/1.1
5630 Host: golang.org
5631 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
5632 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17
5633 Accept-Encoding: gzip,deflate,sdch
5634 Accept-Language: en-US,en;q=0.8
5635 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
5636 `)
5637 res := []byte("Hello world!\n")
5638
5639 conn := &rwTestConn{
5640 Reader: &repeatReader{content: req, count: b.N},
5641 Writer: io.Discard,
5642 closec: make(chan bool, 1),
5643 }
5644 handled := 0
5645 handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
5646 handled++
5647 rw.Header().Set("Content-Type", "text/html; charset=utf-8")
5648 rw.Write(res)
5649 })
5650 ln := &oneConnListener{conn: conn}
5651 go Serve(ln, handler)
5652 <-conn.closec
5653 if b.N != handled {
5654 b.Errorf("b.N=%d but handled %d", b.N, handled)
5655 }
5656 }
5657
5658
5659
5660 func BenchmarkServerFakeConnWithKeepAliveLite(b *testing.B) {
5661 b.ReportAllocs()
5662
5663 req := reqBytes(`GET / HTTP/1.1
5664 Host: golang.org
5665 `)
5666 res := []byte("Hello world!\n")
5667
5668 conn := &rwTestConn{
5669 Reader: &repeatReader{content: req, count: b.N},
5670 Writer: io.Discard,
5671 closec: make(chan bool, 1),
5672 }
5673 handled := 0
5674 handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
5675 handled++
5676 rw.Write(res)
5677 })
5678 ln := &oneConnListener{conn: conn}
5679 go Serve(ln, handler)
5680 <-conn.closec
5681 if b.N != handled {
5682 b.Errorf("b.N=%d but handled %d", b.N, handled)
5683 }
5684 }
5685
5686 const someResponse = "<html>some response</html>"
5687
5688
5689 var response = bytes.Repeat([]byte(someResponse), 2<<10/len(someResponse))
5690
5691
5692 func BenchmarkServerHandlerTypeLen(b *testing.B) {
5693 benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
5694 w.Header().Set("Content-Type", "text/html")
5695 w.Header().Set("Content-Length", strconv.Itoa(len(response)))
5696 w.Write(response)
5697 }))
5698 }
5699
5700
5701 func BenchmarkServerHandlerNoLen(b *testing.B) {
5702 benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
5703 w.Header().Set("Content-Type", "text/html")
5704 w.Write(response)
5705 }))
5706 }
5707
5708
5709 func BenchmarkServerHandlerNoType(b *testing.B) {
5710 benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
5711 w.Header().Set("Content-Length", strconv.Itoa(len(response)))
5712 w.Write(response)
5713 }))
5714 }
5715
5716
5717 func BenchmarkServerHandlerNoHeader(b *testing.B) {
5718 benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
5719 w.Write(response)
5720 }))
5721 }
5722
5723 func benchmarkHandler(b *testing.B, h Handler) {
5724 b.ReportAllocs()
5725 req := reqBytes(`GET / HTTP/1.1
5726 Host: golang.org
5727 `)
5728 conn := &rwTestConn{
5729 Reader: &repeatReader{content: req, count: b.N},
5730 Writer: io.Discard,
5731 closec: make(chan bool, 1),
5732 }
5733 handled := 0
5734 handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
5735 handled++
5736 h.ServeHTTP(rw, r)
5737 })
5738 ln := &oneConnListener{conn: conn}
5739 go Serve(ln, handler)
5740 <-conn.closec
5741 if b.N != handled {
5742 b.Errorf("b.N=%d but handled %d", b.N, handled)
5743 }
5744 }
5745
5746 func BenchmarkServerHijack(b *testing.B) {
5747 b.ReportAllocs()
5748 req := reqBytes(`GET / HTTP/1.1
5749 Host: golang.org
5750 `)
5751 h := HandlerFunc(func(w ResponseWriter, r *Request) {
5752 conn, _, err := w.(Hijacker).Hijack()
5753 if err != nil {
5754 panic(err)
5755 }
5756 conn.Close()
5757 })
5758 conn := &rwTestConn{
5759 Writer: io.Discard,
5760 closec: make(chan bool, 1),
5761 }
5762 ln := &oneConnListener{conn: conn}
5763 for i := 0; i < b.N; i++ {
5764 conn.Reader = bytes.NewReader(req)
5765 ln.conn = conn
5766 Serve(ln, h)
5767 <-conn.closec
5768 }
5769 }
5770
5771 func BenchmarkCloseNotifier(b *testing.B) { run(b, benchmarkCloseNotifier, []testMode{http1Mode}) }
5772 func benchmarkCloseNotifier(b *testing.B, mode testMode) {
5773 b.ReportAllocs()
5774 b.StopTimer()
5775 sawClose := make(chan bool)
5776 ts := newClientServerTest(b, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
5777 <-rw.(CloseNotifier).CloseNotify()
5778 sawClose <- true
5779 })).ts
5780 b.StartTimer()
5781 for i := 0; i < b.N; i++ {
5782 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
5783 if err != nil {
5784 b.Fatalf("error dialing: %v", err)
5785 }
5786 _, err = fmt.Fprintf(conn, "GET / HTTP/1.1\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n")
5787 if err != nil {
5788 b.Fatal(err)
5789 }
5790 conn.Close()
5791 <-sawClose
5792 }
5793 b.StopTimer()
5794 }
5795
5796
5797 func TestConcurrentServerServe(t *testing.T) {
5798 setParallel(t)
5799 for i := 0; i < 100; i++ {
5800 ln1 := &oneConnListener{conn: nil}
5801 ln2 := &oneConnListener{conn: nil}
5802 srv := Server{}
5803 go func() { srv.Serve(ln1) }()
5804 go func() { srv.Serve(ln2) }()
5805 }
5806 }
5807
5808 func TestServerIdleTimeout(t *testing.T) { run(t, testServerIdleTimeout, []testMode{http1Mode}) }
5809 func testServerIdleTimeout(t *testing.T, mode testMode) {
5810 if testing.Short() {
5811 t.Skip("skipping in short mode")
5812 }
5813 runTimeSensitiveTest(t, []time.Duration{
5814 10 * time.Millisecond,
5815 100 * time.Millisecond,
5816 1 * time.Second,
5817 10 * time.Second,
5818 }, func(t *testing.T, readHeaderTimeout time.Duration) error {
5819 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
5820 io.Copy(io.Discard, r.Body)
5821 io.WriteString(w, r.RemoteAddr)
5822 }), func(ts *httptest.Server) {
5823 ts.Config.ReadHeaderTimeout = readHeaderTimeout
5824 ts.Config.IdleTimeout = 2 * readHeaderTimeout
5825 })
5826 defer cst.close()
5827 ts := cst.ts
5828 t.Logf("ReadHeaderTimeout = %v", ts.Config.ReadHeaderTimeout)
5829 t.Logf("IdleTimeout = %v", ts.Config.IdleTimeout)
5830 c := ts.Client()
5831
5832 get := func() (string, error) {
5833 res, err := c.Get(ts.URL)
5834 if err != nil {
5835 return "", err
5836 }
5837 defer res.Body.Close()
5838 slurp, err := io.ReadAll(res.Body)
5839 if err != nil {
5840
5841
5842
5843 t.Fatal(err)
5844 }
5845 return string(slurp), nil
5846 }
5847
5848 a1, err := get()
5849 if err != nil {
5850 return err
5851 }
5852 a2, err := get()
5853 if err != nil {
5854 return err
5855 }
5856 if a1 != a2 {
5857 return fmt.Errorf("did requests on different connections")
5858 }
5859 time.Sleep(ts.Config.IdleTimeout * 3 / 2)
5860 a3, err := get()
5861 if err != nil {
5862 return err
5863 }
5864 if a2 == a3 {
5865 return fmt.Errorf("request three unexpectedly on same connection")
5866 }
5867
5868
5869 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
5870 if err != nil {
5871 return err
5872 }
5873 defer conn.Close()
5874 conn.Write([]byte("GET / HTTP/1.1\r\nHost: foo.com\r\n"))
5875 time.Sleep(ts.Config.ReadHeaderTimeout * 2)
5876 if _, err := io.CopyN(io.Discard, conn, 1); err == nil {
5877 return fmt.Errorf("copy byte succeeded; want err")
5878 }
5879
5880 return nil
5881 })
5882 }
5883
5884 func get(t *testing.T, c *Client, url string) string {
5885 res, err := c.Get(url)
5886 if err != nil {
5887 t.Fatal(err)
5888 }
5889 defer res.Body.Close()
5890 slurp, err := io.ReadAll(res.Body)
5891 if err != nil {
5892 t.Fatal(err)
5893 }
5894 return string(slurp)
5895 }
5896
5897
5898
5899 func TestServerSetKeepAlivesEnabledClosesConns(t *testing.T) {
5900 run(t, testServerSetKeepAlivesEnabledClosesConns, []testMode{http1Mode})
5901 }
5902 func testServerSetKeepAlivesEnabledClosesConns(t *testing.T, mode testMode) {
5903 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
5904 io.WriteString(w, r.RemoteAddr)
5905 })).ts
5906
5907 c := ts.Client()
5908 tr := c.Transport.(*Transport)
5909
5910 get := func() string { return get(t, c, ts.URL) }
5911
5912 a1, a2 := get(), get()
5913 if a1 == a2 {
5914 t.Logf("made two requests from a single conn %q (as expected)", a1)
5915 } else {
5916 t.Errorf("server reported requests from %q and %q; expected same connection", a1, a2)
5917 }
5918
5919
5920
5921
5922
5923 if conns := tr.IdleConnStrsForTesting(); len(conns) != 1 {
5924 t.Errorf("found %d idle conns (%q); want 1", len(conns), conns)
5925 }
5926
5927
5928 ts.Config.SetKeepAlivesEnabled(false)
5929
5930 waitCondition(t, 10*time.Millisecond, func(d time.Duration) bool {
5931 if conns := tr.IdleConnStrsForTesting(); len(conns) > 0 {
5932 if d > 0 {
5933 t.Logf("idle conns %v after SetKeepAlivesEnabled called = %q; waiting for empty", d, conns)
5934 }
5935 return false
5936 }
5937 return true
5938 })
5939
5940
5941
5942
5943 }
5944
5945 func TestServerShutdown(t *testing.T) { run(t, testServerShutdown) }
5946 func testServerShutdown(t *testing.T, mode testMode) {
5947 var cst *clientServerTest
5948
5949 var once sync.Once
5950 statesRes := make(chan map[ConnState]int, 1)
5951 shutdownRes := make(chan error, 1)
5952 gotOnShutdown := make(chan struct{})
5953 handler := HandlerFunc(func(w ResponseWriter, r *Request) {
5954 first := false
5955 once.Do(func() {
5956 statesRes <- cst.ts.Config.ExportAllConnsByState()
5957 go func() {
5958 shutdownRes <- cst.ts.Config.Shutdown(context.Background())
5959 }()
5960 first = true
5961 })
5962
5963 if first {
5964
5965
5966
5967 <-gotOnShutdown
5968
5969
5970 for !t.Failed() {
5971 res, err := cst.c.Get(cst.ts.URL)
5972 if err != nil {
5973 break
5974 }
5975 out, _ := io.ReadAll(res.Body)
5976 res.Body.Close()
5977 if mode == http2Mode {
5978 t.Logf("%v: unexpected success (%q). Listener should be closed before OnShutdown is called.", cst.ts.URL, out)
5979 t.Logf("Retrying to work around https://go.dev/issue/59038.")
5980 continue
5981 }
5982 t.Errorf("%v: unexpected success (%q). Listener should be closed before OnShutdown is called.", cst.ts.URL, out)
5983 }
5984 }
5985
5986 io.WriteString(w, r.RemoteAddr)
5987 })
5988
5989 cst = newClientServerTest(t, mode, handler, func(srv *httptest.Server) {
5990 srv.Config.RegisterOnShutdown(func() { close(gotOnShutdown) })
5991 })
5992
5993 out := get(t, cst.c, cst.ts.URL)
5994 t.Logf("%v: %q", cst.ts.URL, out)
5995
5996 if err := <-shutdownRes; err != nil {
5997 t.Fatalf("Shutdown: %v", err)
5998 }
5999 <-gotOnShutdown
6000
6001 if states := <-statesRes; states[StateActive] != 1 {
6002 t.Errorf("connection in wrong state, %v", states)
6003 }
6004 }
6005
6006 func TestServerShutdownStateNew(t *testing.T) { runSynctest(t, testServerShutdownStateNew) }
6007 func testServerShutdownStateNew(t *testing.T, mode testMode) {
6008 if testing.Short() {
6009 t.Skip("test takes 5-6 seconds; skipping in short mode")
6010 }
6011
6012 listener := fakeNetListen()
6013 defer listener.Close()
6014
6015 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
6016
6017 }), func(ts *httptest.Server) {
6018 ts.Listener.Close()
6019 ts.Listener = listener
6020
6021 ts.Config.ErrorLog = log.New(io.Discard, "", 0)
6022 }).ts
6023
6024
6025 c := listener.connect()
6026 defer c.Close()
6027 synctest.Wait()
6028
6029 shutdownRes := runAsync(func() (struct{}, error) {
6030 return struct{}{}, ts.Config.Shutdown(context.Background())
6031 })
6032
6033
6034
6035
6036 const expectTimeout = 5 * time.Second
6037
6038
6039 time.Sleep(expectTimeout - 1)
6040 synctest.Wait()
6041 if shutdownRes.done() {
6042 t.Fatal("shutdown too soon")
6043 }
6044 if c.IsClosedByPeer() {
6045 t.Fatal("connection was closed by server too soon")
6046 }
6047
6048
6049
6050
6051
6052 time.Sleep(2 * time.Second)
6053 synctest.Wait()
6054 if _, err := shutdownRes.result(); err != nil {
6055 t.Fatalf("Shutdown() = %v, want complete", err)
6056 }
6057 if !c.IsClosedByPeer() {
6058 t.Fatalf("connection was not closed by server after shutdown")
6059 }
6060 }
6061
6062
6063 func TestServerCloseDeadlock(t *testing.T) {
6064 var s Server
6065 s.Close()
6066 s.Close()
6067 }
6068
6069
6070
6071 func TestServerKeepAlivesEnabled(t *testing.T) { run(t, testServerKeepAlivesEnabled, testNotParallel) }
6072 func testServerKeepAlivesEnabled(t *testing.T, mode testMode) {
6073 if mode == http2Mode {
6074 restore := ExportSetH2GoawayTimeout(10 * time.Millisecond)
6075 defer restore()
6076 }
6077
6078 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {}))
6079 defer cst.close()
6080 srv := cst.ts.Config
6081 srv.SetKeepAlivesEnabled(false)
6082 for try := 0; try < 2; try++ {
6083 waitCondition(t, 10*time.Millisecond, func(d time.Duration) bool {
6084 if !srv.ExportAllConnsIdle() {
6085 if d > 0 {
6086 t.Logf("test server still has active conns after %v", d)
6087 }
6088 return false
6089 }
6090 return true
6091 })
6092 conns := 0
6093 var info httptrace.GotConnInfo
6094 ctx := httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{
6095 GotConn: func(v httptrace.GotConnInfo) {
6096 conns++
6097 info = v
6098 },
6099 })
6100 req, err := NewRequestWithContext(ctx, "GET", cst.ts.URL, nil)
6101 if err != nil {
6102 t.Fatal(err)
6103 }
6104 res, err := cst.c.Do(req)
6105 if err != nil {
6106 t.Fatal(err)
6107 }
6108 res.Body.Close()
6109 if conns != 1 {
6110 t.Fatalf("request %v: got %v conns, want 1", try, conns)
6111 }
6112 if info.Reused || info.WasIdle {
6113 t.Fatalf("request %v: Reused=%v (want false), WasIdle=%v (want false)", try, info.Reused, info.WasIdle)
6114 }
6115 }
6116 }
6117
6118
6119
6120
6121 func TestServerCancelsReadTimeoutWhenIdle(t *testing.T) { run(t, testServerCancelsReadTimeoutWhenIdle) }
6122 func testServerCancelsReadTimeoutWhenIdle(t *testing.T, mode testMode) {
6123 runTimeSensitiveTest(t, []time.Duration{
6124 10 * time.Millisecond,
6125 50 * time.Millisecond,
6126 250 * time.Millisecond,
6127 time.Second,
6128 2 * time.Second,
6129 }, func(t *testing.T, timeout time.Duration) error {
6130 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
6131 select {
6132 case <-time.After(2 * timeout):
6133 fmt.Fprint(w, "ok")
6134 case <-r.Context().Done():
6135 fmt.Fprint(w, r.Context().Err())
6136 }
6137 }), func(ts *httptest.Server) {
6138 ts.Config.ReadTimeout = timeout
6139 t.Logf("Server.Config.ReadTimeout = %v", timeout)
6140 })
6141 defer cst.close()
6142 ts := cst.ts
6143
6144 var retries atomic.Int32
6145 cst.c.Transport.(*Transport).Proxy = func(*Request) (*url.URL, error) {
6146 if retries.Add(1) != 1 {
6147 return nil, errors.New("too many retries")
6148 }
6149 return nil, nil
6150 }
6151
6152 c := ts.Client()
6153
6154 res, err := c.Get(ts.URL)
6155 if err != nil {
6156 return fmt.Errorf("Get: %v", err)
6157 }
6158 slurp, err := io.ReadAll(res.Body)
6159 res.Body.Close()
6160 if err != nil {
6161 return fmt.Errorf("Body ReadAll: %v", err)
6162 }
6163 if string(slurp) != "ok" {
6164 return fmt.Errorf("got: %q, want ok", slurp)
6165 }
6166 return nil
6167 })
6168 }
6169
6170
6171
6172
6173 func TestServerCancelsReadHeaderTimeoutWhenIdle(t *testing.T) {
6174 run(t, testServerCancelsReadHeaderTimeoutWhenIdle, []testMode{http1Mode})
6175 }
6176 func testServerCancelsReadHeaderTimeoutWhenIdle(t *testing.T, mode testMode) {
6177 runTimeSensitiveTest(t, []time.Duration{
6178 10 * time.Millisecond,
6179 50 * time.Millisecond,
6180 250 * time.Millisecond,
6181 time.Second,
6182 2 * time.Second,
6183 }, func(t *testing.T, timeout time.Duration) error {
6184 cst := newClientServerTest(t, mode, serve(200), func(ts *httptest.Server) {
6185 ts.Config.ReadHeaderTimeout = timeout
6186 ts.Config.IdleTimeout = 0
6187 })
6188 defer cst.close()
6189 ts := cst.ts
6190
6191
6192
6193 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
6194 if err != nil {
6195 t.Fatalf("dial failed: %v", err)
6196 }
6197 br := bufio.NewReader(conn)
6198 defer conn.Close()
6199
6200 if _, err := conn.Write([]byte("GET / HTTP/1.1\r\nHost: e.com\r\n\r\n")); err != nil {
6201 return fmt.Errorf("writing first request failed: %v", err)
6202 }
6203
6204 if _, err := ReadResponse(br, nil); err != nil {
6205 return fmt.Errorf("first response (before timeout) failed: %v", err)
6206 }
6207
6208
6209
6210 time.Sleep(timeout * 3 / 2)
6211
6212 if _, err := conn.Write([]byte("GET / HTTP/1.1\r\nHost: e.com\r\n\r\n")); err != nil {
6213 return fmt.Errorf("writing second request failed: %v", err)
6214 }
6215
6216 if _, err := ReadResponse(br, nil); err != nil {
6217 return fmt.Errorf("second response (after timeout) failed: %v", err)
6218 }
6219
6220 return nil
6221 })
6222 }
6223
6224
6225
6226 func runTimeSensitiveTest(t *testing.T, durations []time.Duration, test func(t *testing.T, d time.Duration) error) {
6227 for i, d := range durations {
6228 err := test(t, d)
6229 if err == nil {
6230 return
6231 }
6232 if i == len(durations)-1 || t.Failed() {
6233 t.Fatalf("failed with duration %v: %v", d, err)
6234 }
6235 t.Logf("retrying after error with duration %v: %v", d, err)
6236 }
6237 }
6238
6239
6240
6241 func TestServerDuplicateBackgroundRead(t *testing.T) {
6242 run(t, testServerDuplicateBackgroundRead, []testMode{http1Mode})
6243 }
6244 func testServerDuplicateBackgroundRead(t *testing.T, mode testMode) {
6245 if runtime.GOOS == "netbsd" && runtime.GOARCH == "arm" {
6246 testenv.SkipFlaky(t, 24826)
6247 }
6248
6249 goroutines := 5
6250 requests := 2000
6251 if testing.Short() {
6252 goroutines = 3
6253 requests = 100
6254 }
6255
6256 hts := newClientServerTest(t, mode, HandlerFunc(NotFound)).ts
6257
6258 reqBytes := []byte("GET / HTTP/1.1\r\nHost: e.com\r\n\r\n")
6259
6260 var wg sync.WaitGroup
6261 for i := 0; i < goroutines; i++ {
6262 wg.Add(1)
6263 go func() {
6264 defer wg.Done()
6265 cn, err := net.Dial("tcp", hts.Listener.Addr().String())
6266 if err != nil {
6267 t.Error(err)
6268 return
6269 }
6270 defer cn.Close()
6271
6272 wg.Add(1)
6273 go func() {
6274 defer wg.Done()
6275 io.Copy(io.Discard, cn)
6276 }()
6277
6278 for j := 0; j < requests; j++ {
6279 if t.Failed() {
6280 return
6281 }
6282 _, err := cn.Write(reqBytes)
6283 if err != nil {
6284 t.Error(err)
6285 return
6286 }
6287 }
6288 }()
6289 }
6290 wg.Wait()
6291 }
6292
6293
6294
6295
6296
6297
6298 func TestServerHijackGetsBackgroundByte(t *testing.T) {
6299 run(t, testServerHijackGetsBackgroundByte, []testMode{http1Mode})
6300 }
6301 func testServerHijackGetsBackgroundByte(t *testing.T, mode testMode) {
6302 if runtime.GOOS == "plan9" {
6303 t.Skip("skipping test; see https://golang.org/issue/18657")
6304 }
6305 done := make(chan struct{})
6306 inHandler := make(chan bool, 1)
6307 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
6308 defer close(done)
6309
6310
6311 inHandler <- true
6312
6313 conn, buf, err := w.(Hijacker).Hijack()
6314 if err != nil {
6315 t.Error(err)
6316 return
6317 }
6318 defer conn.Close()
6319
6320 peek, err := buf.Reader.Peek(3)
6321 if string(peek) != "foo" || err != nil {
6322 t.Errorf("Peek = %q, %v; want foo, nil", peek, err)
6323 }
6324
6325 select {
6326 case <-r.Context().Done():
6327 t.Error("context unexpectedly canceled")
6328 default:
6329 }
6330 })).ts
6331
6332 cn, err := net.Dial("tcp", ts.Listener.Addr().String())
6333 if err != nil {
6334 t.Fatal(err)
6335 }
6336 defer cn.Close()
6337 if _, err := cn.Write([]byte("GET / HTTP/1.1\r\nHost: e.com\r\n\r\n")); err != nil {
6338 t.Fatal(err)
6339 }
6340 <-inHandler
6341 if _, err := cn.Write([]byte("foo")); err != nil {
6342 t.Fatal(err)
6343 }
6344
6345 if err := cn.(*net.TCPConn).CloseWrite(); err != nil {
6346 t.Fatal(err)
6347 }
6348 <-done
6349 }
6350
6351
6352 func TestServerHijackGetsFullBody(t *testing.T) {
6353 run(t, testServerHijackGetsFullBody, []testMode{http1Mode})
6354 }
6355 func testServerHijackGetsFullBody(t *testing.T, mode testMode) {
6356 if runtime.GOOS == "plan9" {
6357 t.Skip("skipping test; see https://golang.org/issue/18657")
6358 }
6359 done := make(chan struct{})
6360 needle := strings.Repeat("x", 100*1024)
6361 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
6362 defer close(done)
6363
6364 conn, buf, err := w.(Hijacker).Hijack()
6365 if err != nil {
6366 t.Error(err)
6367 return
6368 }
6369 defer conn.Close()
6370
6371 got := make([]byte, len(needle))
6372 n, err := io.ReadFull(buf.Reader, got)
6373 if n != len(needle) || string(got) != needle || err != nil {
6374 t.Errorf("Peek = %q, %v; want 'x'*4096, nil", got, err)
6375 }
6376 })).ts
6377
6378 cn, err := net.Dial("tcp", ts.Listener.Addr().String())
6379 if err != nil {
6380 t.Fatal(err)
6381 }
6382 defer cn.Close()
6383 buf := []byte("GET / HTTP/1.1\r\nHost: e.com\r\n\r\n")
6384 buf = append(buf, []byte(needle)...)
6385 if _, err := cn.Write(buf); err != nil {
6386 t.Fatal(err)
6387 }
6388
6389 if err := cn.(*net.TCPConn).CloseWrite(); err != nil {
6390 t.Fatal(err)
6391 }
6392 <-done
6393 }
6394
6395
6396
6397
6398 func TestServerHijackGetsBackgroundByte_big(t *testing.T) {
6399 run(t, testServerHijackGetsBackgroundByte_big, []testMode{http1Mode})
6400 }
6401 func testServerHijackGetsBackgroundByte_big(t *testing.T, mode testMode) {
6402 if runtime.GOOS == "plan9" {
6403 t.Skip("skipping test; see https://golang.org/issue/18657")
6404 }
6405 done := make(chan struct{})
6406 const size = 8 << 10
6407 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
6408 defer close(done)
6409
6410 conn, buf, err := w.(Hijacker).Hijack()
6411 if err != nil {
6412 t.Error(err)
6413 return
6414 }
6415 defer conn.Close()
6416 slurp, err := io.ReadAll(buf.Reader)
6417 if err != nil {
6418 t.Errorf("Copy: %v", err)
6419 }
6420 allX := true
6421 for _, v := range slurp {
6422 if v != 'x' {
6423 allX = false
6424 }
6425 }
6426 if len(slurp) != size {
6427 t.Errorf("read %d; want %d", len(slurp), size)
6428 } else if !allX {
6429 t.Errorf("read %q; want %d 'x'", slurp, size)
6430 }
6431 })).ts
6432
6433 cn, err := net.Dial("tcp", ts.Listener.Addr().String())
6434 if err != nil {
6435 t.Fatal(err)
6436 }
6437 defer cn.Close()
6438 if _, err := fmt.Fprintf(cn, "GET / HTTP/1.1\r\nHost: e.com\r\n\r\n%s",
6439 strings.Repeat("x", size)); err != nil {
6440 t.Fatal(err)
6441 }
6442 if err := cn.(*net.TCPConn).CloseWrite(); err != nil {
6443 t.Fatal(err)
6444 }
6445
6446 <-done
6447 }
6448
6449
6450 func TestServerValidatesMethod(t *testing.T) {
6451 tests := []struct {
6452 method string
6453 want int
6454 }{
6455 {"GET", 200},
6456 {"GE(T", 400},
6457 }
6458 for _, tt := range tests {
6459 conn := newTestConn()
6460 io.WriteString(&conn.readBuf, tt.method+" / HTTP/1.1\r\nHost: foo.example\r\n\r\n")
6461
6462 ln := &oneConnListener{conn}
6463 go Serve(ln, serve(200))
6464 <-conn.closec
6465 res, err := ReadResponse(bufio.NewReader(&conn.writeBuf), nil)
6466 if err != nil {
6467 t.Errorf("For %s, ReadResponse: %v", tt.method, res)
6468 continue
6469 }
6470 if res.StatusCode != tt.want {
6471 t.Errorf("For %s, Status = %d; want %d", tt.method, res.StatusCode, tt.want)
6472 }
6473 }
6474 }
6475
6476
6477 type eofListenerNotComparable []int
6478
6479 func (eofListenerNotComparable) Accept() (net.Conn, error) { return nil, io.EOF }
6480 func (eofListenerNotComparable) Addr() net.Addr { return nil }
6481 func (eofListenerNotComparable) Close() error { return nil }
6482
6483
6484 func TestServerListenNotComparableListener(t *testing.T) {
6485 var s Server
6486 s.Serve(make(eofListenerNotComparable, 1))
6487 }
6488
6489
6490 type countCloseListener struct {
6491 net.Listener
6492 closes int32
6493 }
6494
6495 func (p *countCloseListener) Close() error {
6496 var err error
6497 if n := atomic.AddInt32(&p.closes, 1); n == 1 && p.Listener != nil {
6498 err = p.Listener.Close()
6499 }
6500 return err
6501 }
6502
6503
6504 func TestServerCloseListenerOnce(t *testing.T) {
6505 setParallel(t)
6506 defer afterTest(t)
6507
6508 ln := newLocalListener(t)
6509 defer ln.Close()
6510
6511 cl := &countCloseListener{Listener: ln}
6512 server := &Server{}
6513 sdone := make(chan bool, 1)
6514
6515 go func() {
6516 server.Serve(cl)
6517 sdone <- true
6518 }()
6519 time.Sleep(10 * time.Millisecond)
6520 server.Shutdown(context.Background())
6521 ln.Close()
6522 <-sdone
6523
6524 nclose := atomic.LoadInt32(&cl.closes)
6525 if nclose != 1 {
6526 t.Errorf("Close calls = %v; want 1", nclose)
6527 }
6528 }
6529
6530
6531 func TestServerShutdownThenServe(t *testing.T) {
6532 var srv Server
6533 cl := &countCloseListener{Listener: nil}
6534 srv.Shutdown(context.Background())
6535 got := srv.Serve(cl)
6536 if got != ErrServerClosed {
6537 t.Errorf("Serve err = %v; want ErrServerClosed", got)
6538 }
6539 nclose := atomic.LoadInt32(&cl.closes)
6540 if nclose != 1 {
6541 t.Errorf("Close calls = %v; want 1", nclose)
6542 }
6543 }
6544
6545
6546 func TestStripPortFromHost(t *testing.T) {
6547 mux := NewServeMux()
6548
6549 mux.HandleFunc("example.com/", func(w ResponseWriter, r *Request) {
6550 fmt.Fprintf(w, "OK")
6551 })
6552 mux.HandleFunc("example.com:9000/", func(w ResponseWriter, r *Request) {
6553 fmt.Fprintf(w, "uh-oh!")
6554 })
6555
6556 req := httptest.NewRequest("GET", "http://example.com:9000/", nil)
6557 rw := httptest.NewRecorder()
6558
6559 mux.ServeHTTP(rw, req)
6560
6561 response := rw.Body.String()
6562 if response != "OK" {
6563 t.Errorf("Response gotten was %q", response)
6564 }
6565 }
6566
6567 func TestServerContexts(t *testing.T) { run(t, testServerContexts) }
6568 func testServerContexts(t *testing.T, mode testMode) {
6569 type baseKey struct{}
6570 type connKey struct{}
6571 ch := make(chan context.Context, 1)
6572 ts := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, r *Request) {
6573 ch <- r.Context()
6574 }), func(ts *httptest.Server) {
6575 ts.Config.BaseContext = func(ln net.Listener) context.Context {
6576 if strings.Contains(reflect.TypeOf(ln).String(), "onceClose") {
6577 t.Errorf("unexpected onceClose listener type %T", ln)
6578 }
6579 return context.WithValue(context.Background(), baseKey{}, "base")
6580 }
6581 ts.Config.ConnContext = func(ctx context.Context, c net.Conn) context.Context {
6582 if got, want := ctx.Value(baseKey{}), "base"; got != want {
6583 t.Errorf("in ConnContext, base context key = %#v; want %q", got, want)
6584 }
6585 return context.WithValue(ctx, connKey{}, "conn")
6586 }
6587 }).ts
6588 res, err := ts.Client().Get(ts.URL)
6589 if err != nil {
6590 t.Fatal(err)
6591 }
6592 res.Body.Close()
6593 ctx := <-ch
6594 if got, want := ctx.Value(baseKey{}), "base"; got != want {
6595 t.Errorf("base context key = %#v; want %q", got, want)
6596 }
6597 if got, want := ctx.Value(connKey{}), "conn"; got != want {
6598 t.Errorf("conn context key = %#v; want %q", got, want)
6599 }
6600 }
6601
6602
6603 func TestConnContextNotModifyingAllContexts(t *testing.T) {
6604 run(t, testConnContextNotModifyingAllContexts)
6605 }
6606 func testConnContextNotModifyingAllContexts(t *testing.T, mode testMode) {
6607 type connKey struct{}
6608 ts := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, r *Request) {
6609 rw.Header().Set("Connection", "close")
6610 }), func(ts *httptest.Server) {
6611 ts.Config.ConnContext = func(ctx context.Context, c net.Conn) context.Context {
6612 if got := ctx.Value(connKey{}); got != nil {
6613 t.Errorf("in ConnContext, unexpected context key = %#v", got)
6614 }
6615 return context.WithValue(ctx, connKey{}, "conn")
6616 }
6617 }).ts
6618
6619 var res *Response
6620 var err error
6621
6622 res, err = ts.Client().Get(ts.URL)
6623 if err != nil {
6624 t.Fatal(err)
6625 }
6626 res.Body.Close()
6627
6628 res, err = ts.Client().Get(ts.URL)
6629 if err != nil {
6630 t.Fatal(err)
6631 }
6632 res.Body.Close()
6633 }
6634
6635
6636
6637 func TestUnsupportedTransferEncodingsReturn501(t *testing.T) {
6638 run(t, testUnsupportedTransferEncodingsReturn501, []testMode{http1Mode})
6639 }
6640 func testUnsupportedTransferEncodingsReturn501(t *testing.T, mode testMode) {
6641 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
6642 w.Write([]byte("Hello, World!"))
6643 })).ts
6644
6645 serverURL, err := url.Parse(cst.URL)
6646 if err != nil {
6647 t.Fatalf("Failed to parse server URL: %v", err)
6648 }
6649
6650 unsupportedTEs := []string{
6651 "fugazi",
6652 "foo-bar",
6653 "unknown",
6654 `" chunked"`,
6655 }
6656
6657 for _, badTE := range unsupportedTEs {
6658 http1ReqBody := fmt.Sprintf(""+
6659 "POST / HTTP/1.1\r\nConnection: close\r\n"+
6660 "Host: localhost\r\nTransfer-Encoding: %s\r\n\r\n", badTE)
6661
6662 gotBody, err := fetchWireResponse(serverURL.Host, []byte(http1ReqBody))
6663 if err != nil {
6664 t.Errorf("%q. unexpected error: %v", badTE, err)
6665 continue
6666 }
6667
6668 wantBody := fmt.Sprintf("" +
6669 "HTTP/1.1 501 Not Implemented\r\nContent-Type: text/plain; charset=utf-8\r\n" +
6670 "Connection: close\r\n\r\nUnsupported transfer encoding")
6671
6672 if string(gotBody) != wantBody {
6673 t.Errorf("%q. body\ngot\n%q\nwant\n%q", badTE, gotBody, wantBody)
6674 }
6675 }
6676 }
6677
6678
6679 func TestContentEncodingNoSniffing(t *testing.T) { run(t, testContentEncodingNoSniffing) }
6680 func testContentEncodingNoSniffing(t *testing.T, mode testMode) {
6681 type setting struct {
6682 name string
6683 body []byte
6684
6685
6686
6687
6688 contentEncoding any
6689 wantContentType string
6690 }
6691
6692 settings := []*setting{
6693 {
6694 name: "gzip content-encoding, gzipped",
6695 contentEncoding: "application/gzip",
6696 wantContentType: "",
6697 body: func() []byte {
6698 buf := new(bytes.Buffer)
6699 gzw := gzip.NewWriter(buf)
6700 gzw.Write([]byte("doctype html><p>Hello</p>"))
6701 gzw.Close()
6702 return buf.Bytes()
6703 }(),
6704 },
6705 {
6706 name: "zlib content-encoding, zlibbed",
6707 contentEncoding: "application/zlib",
6708 wantContentType: "",
6709 body: func() []byte {
6710 buf := new(bytes.Buffer)
6711 zw := zlib.NewWriter(buf)
6712 zw.Write([]byte("doctype html><p>Hello</p>"))
6713 zw.Close()
6714 return buf.Bytes()
6715 }(),
6716 },
6717 {
6718 name: "no content-encoding",
6719 wantContentType: "application/x-gzip",
6720 body: func() []byte {
6721 buf := new(bytes.Buffer)
6722 gzw := gzip.NewWriter(buf)
6723 gzw.Write([]byte("doctype html><p>Hello</p>"))
6724 gzw.Close()
6725 return buf.Bytes()
6726 }(),
6727 },
6728 {
6729 name: "phony content-encoding",
6730 contentEncoding: "foo/bar",
6731 body: []byte("doctype html><p>Hello</p>"),
6732 },
6733 {
6734 name: "empty but set content-encoding",
6735 contentEncoding: "",
6736 wantContentType: "audio/mpeg",
6737 body: []byte("ID3"),
6738 },
6739 }
6740
6741 for _, tt := range settings {
6742 t.Run(tt.name, func(t *testing.T) {
6743 cst := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, r *Request) {
6744 if tt.contentEncoding != nil {
6745 rw.Header().Set("Content-Encoding", tt.contentEncoding.(string))
6746 }
6747 rw.Write(tt.body)
6748 }))
6749
6750 res, err := cst.c.Get(cst.ts.URL)
6751 if err != nil {
6752 t.Fatalf("Failed to fetch URL: %v", err)
6753 }
6754 defer res.Body.Close()
6755
6756 if g, w := res.Header.Get("Content-Encoding"), tt.contentEncoding; g != w {
6757 if w != nil {
6758 t.Errorf("Content-Encoding mismatch\n\tgot: %q\n\twant: %q", g, w)
6759 } else if g != "" {
6760 t.Errorf("Unexpected Content-Encoding %q", g)
6761 }
6762 }
6763
6764 if g, w := res.Header.Get("Content-Type"), tt.wantContentType; g != w {
6765 t.Errorf("Content-Type mismatch\n\tgot: %q\n\twant: %q", g, w)
6766 }
6767 })
6768 }
6769 }
6770
6771
6772
6773 func TestTimeoutHandlerSuperfluousLogs(t *testing.T) {
6774 run(t, testTimeoutHandlerSuperfluousLogs, []testMode{http1Mode})
6775 }
6776 func testTimeoutHandlerSuperfluousLogs(t *testing.T, mode testMode) {
6777 if testing.Short() {
6778 t.Skip("skipping in short mode")
6779 }
6780
6781 pc, curFile, _, _ := runtime.Caller(0)
6782 curFileBaseName := filepath.Base(curFile)
6783 testFuncName := runtime.FuncForPC(pc).Name()
6784
6785 timeoutMsg := "timed out here!"
6786
6787 tests := []struct {
6788 name string
6789 mustTimeout bool
6790 wantResp string
6791 }{
6792 {
6793 name: "return before timeout",
6794 wantResp: "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n",
6795 },
6796 {
6797 name: "return after timeout",
6798 mustTimeout: true,
6799 wantResp: fmt.Sprintf("HTTP/1.1 503 Service Unavailable\r\nContent-Length: %d\r\n\r\n%s",
6800 len(timeoutMsg), timeoutMsg),
6801 },
6802 }
6803
6804 for _, tt := range tests {
6805 t.Run(tt.name, func(t *testing.T) {
6806 exitHandler := make(chan bool, 1)
6807 defer close(exitHandler)
6808 lastLine := make(chan int, 1)
6809
6810 sh := HandlerFunc(func(w ResponseWriter, r *Request) {
6811 w.WriteHeader(404)
6812 w.WriteHeader(404)
6813 w.WriteHeader(404)
6814 w.WriteHeader(404)
6815 _, _, line, _ := runtime.Caller(0)
6816 lastLine <- line
6817 <-exitHandler
6818 })
6819
6820 if !tt.mustTimeout {
6821 exitHandler <- true
6822 }
6823
6824 logBuf := new(strings.Builder)
6825 srvLog := log.New(logBuf, "", 0)
6826
6827 dur := 20 * time.Millisecond
6828 if !tt.mustTimeout {
6829
6830 dur = 10 * time.Second
6831 }
6832 th := TimeoutHandler(sh, dur, timeoutMsg)
6833 cst := newClientServerTest(t, mode, th, optWithServerLog(srvLog))
6834 defer cst.close()
6835
6836 res, err := cst.c.Get(cst.ts.URL)
6837 if err != nil {
6838 t.Fatalf("Unexpected error: %v", err)
6839 }
6840
6841
6842
6843 res.Header.Del("Date")
6844 res.Header.Del("Content-Type")
6845
6846
6847 blob, _ := httputil.DumpResponse(res, true)
6848 if g, w := string(blob), tt.wantResp; g != w {
6849 t.Errorf("Response mismatch\nGot\n%q\n\nWant\n%q", g, w)
6850 }
6851
6852
6853
6854 logEntries := strings.Split(strings.TrimSpace(logBuf.String()), "\n")
6855 if g, w := len(logEntries), 3; g != w {
6856 blob, _ := json.MarshalIndent(logEntries, "", " ")
6857 t.Fatalf("Server logs count mismatch\ngot %d, want %d\n\nGot\n%s\n", g, w, blob)
6858 }
6859
6860 lastSpuriousLine := <-lastLine
6861 firstSpuriousLine := lastSpuriousLine - 3
6862
6863
6864 for i, logEntry := range logEntries {
6865 wantLine := firstSpuriousLine + i
6866 pat := fmt.Sprintf("^http: superfluous response.WriteHeader call from %s.func\\d+.\\d+ \\(%s:%d\\)$",
6867 testFuncName, curFileBaseName, wantLine)
6868 re := regexp.MustCompile(pat)
6869 if !re.MatchString(logEntry) {
6870 t.Errorf("Log entry mismatch\n\t%s\ndoes not match\n\t%s", logEntry, pat)
6871 }
6872 }
6873 })
6874 }
6875 }
6876
6877
6878
6879
6880 func fetchWireResponse(host string, http1ReqBody []byte) ([]byte, error) {
6881 conn, err := net.Dial("tcp", host)
6882 if err != nil {
6883 return nil, err
6884 }
6885 defer conn.Close()
6886
6887 if _, err := conn.Write(http1ReqBody); err != nil {
6888 return nil, err
6889 }
6890 return io.ReadAll(conn)
6891 }
6892
6893 func BenchmarkResponseStatusLine(b *testing.B) {
6894 b.ReportAllocs()
6895 b.RunParallel(func(pb *testing.PB) {
6896 bw := bufio.NewWriter(io.Discard)
6897 var buf3 [3]byte
6898 for pb.Next() {
6899 Export_writeStatusLine(bw, true, 200, buf3[:])
6900 }
6901 })
6902 }
6903
6904 func TestDisableKeepAliveUpgrade(t *testing.T) {
6905 run(t, testDisableKeepAliveUpgrade, []testMode{http1Mode})
6906 }
6907 func testDisableKeepAliveUpgrade(t *testing.T, mode testMode) {
6908 if testing.Short() {
6909 t.Skip("skipping in short mode")
6910 }
6911
6912 s := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
6913 w.Header().Set("Connection", "Upgrade")
6914 w.Header().Set("Upgrade", "someProto")
6915 w.WriteHeader(StatusSwitchingProtocols)
6916 c, buf, err := w.(Hijacker).Hijack()
6917 if err != nil {
6918 return
6919 }
6920 defer c.Close()
6921
6922
6923
6924 io.Copy(c, buf)
6925 }), func(ts *httptest.Server) {
6926 ts.Config.SetKeepAlivesEnabled(false)
6927 }).ts
6928
6929 cl := s.Client()
6930 cl.Transport.(*Transport).DisableKeepAlives = true
6931
6932 resp, err := cl.Get(s.URL)
6933 if err != nil {
6934 t.Fatalf("failed to perform request: %v", err)
6935 }
6936 defer resp.Body.Close()
6937
6938 if resp.StatusCode != StatusSwitchingProtocols {
6939 t.Fatalf("unexpected status code: %v", resp.StatusCode)
6940 }
6941
6942 rwc, ok := resp.Body.(io.ReadWriteCloser)
6943 if !ok {
6944 t.Fatalf("Response.Body is not an io.ReadWriteCloser: %T", resp.Body)
6945 }
6946
6947 _, err = rwc.Write([]byte("hello"))
6948 if err != nil {
6949 t.Fatalf("failed to write to body: %v", err)
6950 }
6951
6952 b := make([]byte, 5)
6953 _, err = io.ReadFull(rwc, b)
6954 if err != nil {
6955 t.Fatalf("failed to read from body: %v", err)
6956 }
6957
6958 if string(b) != "hello" {
6959 t.Fatalf("unexpected value read from body:\ngot: %q\nwant: %q", b, "hello")
6960 }
6961 }
6962
6963 type tlogWriter struct{ t *testing.T }
6964
6965 func (w tlogWriter) Write(p []byte) (int, error) {
6966 w.t.Log(string(p))
6967 return len(p), nil
6968 }
6969
6970 func TestWriteHeaderSwitchingProtocols(t *testing.T) {
6971 run(t, testWriteHeaderSwitchingProtocols, []testMode{http1Mode})
6972 }
6973 func testWriteHeaderSwitchingProtocols(t *testing.T, mode testMode) {
6974 const wantBody = "want"
6975 const wantUpgrade = "someProto"
6976 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
6977 w.Header().Set("Connection", "Upgrade")
6978 w.Header().Set("Upgrade", wantUpgrade)
6979 w.WriteHeader(StatusSwitchingProtocols)
6980 NewResponseController(w).Flush()
6981
6982
6983 w.WriteHeader(200)
6984 if _, err := w.Write([]byte("x")); err == nil {
6985 t.Errorf("Write to body after 101 Switching Protocols unexpectedly succeeded")
6986 }
6987
6988 c, _, err := NewResponseController(w).Hijack()
6989 if err != nil {
6990 t.Errorf("Hijack: %v", err)
6991 return
6992 }
6993 defer c.Close()
6994 if _, err := c.Write([]byte(wantBody)); err != nil {
6995 t.Errorf("Write to hijacked body: %v", err)
6996 }
6997 }), func(ts *httptest.Server) {
6998
6999 ts.Config.ErrorLog = log.New(tlogWriter{t}, "log: ", 0)
7000 }).ts
7001
7002 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
7003 if err != nil {
7004 t.Fatalf("net.Dial: %v", err)
7005 }
7006 _, err = conn.Write([]byte("GET / HTTP/1.1\r\nHost: foo\r\n\r\n"))
7007 if err != nil {
7008 t.Fatalf("conn.Write: %v", err)
7009 }
7010 defer conn.Close()
7011
7012 r := bufio.NewReader(conn)
7013 res, err := ReadResponse(r, &Request{Method: "GET"})
7014 if err != nil {
7015 t.Fatal("ReadResponse error:", err)
7016 }
7017 if res.StatusCode != StatusSwitchingProtocols {
7018 t.Errorf("Response StatusCode=%v, want 101", res.StatusCode)
7019 }
7020 if got := res.Header.Get("Upgrade"); got != wantUpgrade {
7021 t.Errorf("Response Upgrade header = %q, want %q", got, wantUpgrade)
7022 }
7023 body, err := io.ReadAll(r)
7024 if err != nil {
7025 t.Error(err)
7026 }
7027 if string(body) != wantBody {
7028 t.Errorf("Response body = %q, want %q", string(body), wantBody)
7029 }
7030 }
7031
7032 func TestMuxRedirectRelative(t *testing.T) {
7033 setParallel(t)
7034 req, err := ReadRequest(bufio.NewReader(strings.NewReader("GET http://example.com HTTP/1.1\r\nHost: test\r\n\r\n")))
7035 if err != nil {
7036 t.Errorf("%s", err)
7037 }
7038 mux := NewServeMux()
7039 resp := httptest.NewRecorder()
7040 mux.ServeHTTP(resp, req)
7041 if got, want := resp.Header().Get("Location"), "/"; got != want {
7042 t.Errorf("Location header expected %q; got %q", want, got)
7043 }
7044 if got, want := resp.Code, StatusTemporaryRedirect; got != want {
7045 t.Errorf("Expected response code %d; got %d", want, got)
7046 }
7047 }
7048
7049
7050 func TestQuerySemicolon(t *testing.T) {
7051 t.Cleanup(func() { afterTest(t) })
7052
7053 tests := []struct {
7054 query string
7055 xNoSemicolons string
7056 xWithSemicolons string
7057 expectParseFormErr bool
7058 }{
7059 {"?a=1;x=bad&x=good", "good", "bad", true},
7060 {"?a=1;b=bad&x=good", "good", "good", true},
7061 {"?a=1%3Bx=bad&x=good%3B", "good;", "good;", false},
7062 {"?a=1;x=good;x=bad", "", "good", true},
7063 }
7064
7065 run(t, func(t *testing.T, mode testMode) {
7066 for _, tt := range tests {
7067 t.Run(tt.query+"/allow=false", func(t *testing.T) {
7068 allowSemicolons := false
7069 testQuerySemicolon(t, mode, tt.query, tt.xNoSemicolons, allowSemicolons, tt.expectParseFormErr)
7070 })
7071 t.Run(tt.query+"/allow=true", func(t *testing.T) {
7072 allowSemicolons, expectParseFormErr := true, false
7073 testQuerySemicolon(t, mode, tt.query, tt.xWithSemicolons, allowSemicolons, expectParseFormErr)
7074 })
7075 }
7076 })
7077 }
7078
7079 func testQuerySemicolon(t *testing.T, mode testMode, query string, wantX string, allowSemicolons, expectParseFormErr bool) {
7080 writeBackX := func(w ResponseWriter, r *Request) {
7081 x := r.URL.Query().Get("x")
7082 if expectParseFormErr {
7083 if err := r.ParseForm(); err == nil || !strings.Contains(err.Error(), "semicolon") {
7084 t.Errorf("expected error mentioning semicolons from ParseForm, got %v", err)
7085 }
7086 } else {
7087 if err := r.ParseForm(); err != nil {
7088 t.Errorf("expected no error from ParseForm, got %v", err)
7089 }
7090 }
7091 if got := r.FormValue("x"); x != got {
7092 t.Errorf("got %q from FormValue, want %q", got, x)
7093 }
7094 fmt.Fprintf(w, "%s", x)
7095 }
7096
7097 h := Handler(HandlerFunc(writeBackX))
7098 if allowSemicolons {
7099 h = AllowQuerySemicolons(h)
7100 }
7101
7102 logBuf := &strings.Builder{}
7103 ts := newClientServerTest(t, mode, h, func(ts *httptest.Server) {
7104 ts.Config.ErrorLog = log.New(logBuf, "", 0)
7105 }).ts
7106
7107 req, _ := NewRequest("GET", ts.URL+query, nil)
7108 res, err := ts.Client().Do(req)
7109 if err != nil {
7110 t.Fatal(err)
7111 }
7112 slurp, _ := io.ReadAll(res.Body)
7113 res.Body.Close()
7114 if got, want := res.StatusCode, 200; got != want {
7115 t.Errorf("Status = %d; want = %d", got, want)
7116 }
7117 if got, want := string(slurp), wantX; got != want {
7118 t.Errorf("Body = %q; want = %q", got, want)
7119 }
7120 }
7121
7122 func TestMaxBytesHandler(t *testing.T) {
7123
7124 defer afterTest(t)
7125
7126 for _, maxSize := range []int64{100, 1_000, 1_000_000} {
7127 for _, requestSize := range []int64{100, 1_000, 1_000_000} {
7128 t.Run(fmt.Sprintf("max size %d request size %d", maxSize, requestSize),
7129 func(t *testing.T) {
7130 run(t, func(t *testing.T, mode testMode) {
7131 testMaxBytesHandler(t, mode, maxSize, requestSize)
7132 }, testNotParallel)
7133 })
7134 }
7135 }
7136 }
7137
7138 func testMaxBytesHandler(t *testing.T, mode testMode, maxSize, requestSize int64) {
7139 runTimeSensitiveTest(t, []time.Duration{
7140 1 * time.Millisecond,
7141 5 * time.Millisecond,
7142 10 * time.Millisecond,
7143 50 * time.Millisecond,
7144 100 * time.Millisecond,
7145 500 * time.Millisecond,
7146 time.Second,
7147 5 * time.Second,
7148 }, func(t *testing.T, timeout time.Duration) error {
7149 SetRSTAvoidanceDelay(t, timeout)
7150 t.Logf("set RST avoidance delay to %v", timeout)
7151
7152 var (
7153 handlerN int64
7154 handlerErr error
7155 )
7156 echo := HandlerFunc(func(w ResponseWriter, r *Request) {
7157 var buf bytes.Buffer
7158 handlerN, handlerErr = io.Copy(&buf, r.Body)
7159 io.Copy(w, &buf)
7160 })
7161
7162 cst := newClientServerTest(t, mode, MaxBytesHandler(echo, maxSize))
7163
7164
7165 defer cst.close()
7166 ts := cst.ts
7167 c := ts.Client()
7168
7169 body := strings.Repeat("a", int(requestSize))
7170 var wg sync.WaitGroup
7171 defer wg.Wait()
7172 getBody := func() (io.ReadCloser, error) {
7173 wg.Add(1)
7174 body := &wgReadCloser{
7175 Reader: strings.NewReader(body),
7176 wg: &wg,
7177 }
7178 return body, nil
7179 }
7180 reqBody, _ := getBody()
7181 req, err := NewRequest("POST", ts.URL, reqBody)
7182 if err != nil {
7183 reqBody.Close()
7184 t.Fatal(err)
7185 }
7186 req.ContentLength = int64(len(body))
7187 req.GetBody = getBody
7188 req.Header.Set("Content-Type", "text/plain")
7189
7190 var buf strings.Builder
7191 res, err := c.Do(req)
7192 if err != nil {
7193 return fmt.Errorf("unexpected connection error: %v", err)
7194 } else {
7195 _, err = io.Copy(&buf, res.Body)
7196 res.Body.Close()
7197 if err != nil {
7198 return fmt.Errorf("unexpected read error: %v", err)
7199 }
7200 }
7201
7202
7203
7204
7205 if handlerN > maxSize {
7206 t.Errorf("expected max request body %d; got %d", maxSize, handlerN)
7207 }
7208 if requestSize > maxSize && handlerErr == nil {
7209 t.Error("expected error on handler side; got nil")
7210 }
7211 if requestSize <= maxSize {
7212 if handlerErr != nil {
7213 t.Errorf("%d expected nil error on handler side; got %v", requestSize, handlerErr)
7214 }
7215 if handlerN != requestSize {
7216 t.Errorf("expected request of size %d; got %d", requestSize, handlerN)
7217 }
7218 }
7219 if buf.Len() != int(handlerN) {
7220 t.Errorf("expected echo of size %d; got %d", handlerN, buf.Len())
7221 }
7222
7223 return nil
7224 })
7225 }
7226
7227 func TestEarlyHints(t *testing.T) {
7228 ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
7229 h := w.Header()
7230 h.Add("Link", "</style.css>; rel=preload; as=style")
7231 h.Add("Link", "</script.js>; rel=preload; as=script")
7232 w.WriteHeader(StatusEarlyHints)
7233
7234 h.Add("Link", "</foo.js>; rel=preload; as=script")
7235 w.WriteHeader(StatusEarlyHints)
7236
7237 w.Write([]byte("stuff"))
7238 }))
7239
7240 got := ht.rawResponse("GET / HTTP/1.1\nHost: golang.org")
7241 expected := "HTTP/1.1 103 Early Hints\r\nLink: </style.css>; rel=preload; as=style\r\nLink: </script.js>; rel=preload; as=script\r\n\r\nHTTP/1.1 103 Early Hints\r\nLink: </style.css>; rel=preload; as=style\r\nLink: </script.js>; rel=preload; as=script\r\nLink: </foo.js>; rel=preload; as=script\r\n\r\nHTTP/1.1 200 OK\r\nLink: </style.css>; rel=preload; as=style\r\nLink: </script.js>; rel=preload; as=script\r\nLink: </foo.js>; rel=preload; as=script\r\nDate: "
7242 if !strings.Contains(got, expected) {
7243 t.Errorf("unexpected response; got %q; should start by %q", got, expected)
7244 }
7245 }
7246 func TestProcessing(t *testing.T) {
7247 ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
7248 w.WriteHeader(StatusProcessing)
7249 w.Write([]byte("stuff"))
7250 }))
7251
7252 got := ht.rawResponse("GET / HTTP/1.1\nHost: golang.org")
7253 expected := "HTTP/1.1 102 Processing\r\n\r\nHTTP/1.1 200 OK\r\nDate: "
7254 if !strings.Contains(got, expected) {
7255 t.Errorf("unexpected response; got %q; should start by %q", got, expected)
7256 }
7257 }
7258
7259 func TestParseFormCleanup(t *testing.T) { run(t, testParseFormCleanup) }
7260 func testParseFormCleanup(t *testing.T, mode testMode) {
7261 if mode == http2Mode {
7262 t.Skip("https://go.dev/issue/20253")
7263 }
7264
7265 const maxMemory = 1024
7266 const key = "file"
7267
7268 if runtime.GOOS == "windows" {
7269
7270 t.Skip("https://go.dev/issue/25965")
7271 }
7272
7273 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
7274 r.ParseMultipartForm(maxMemory)
7275 f, _, err := r.FormFile(key)
7276 if err != nil {
7277 t.Errorf("r.FormFile(%q) = %v", key, err)
7278 return
7279 }
7280 of, ok := f.(*os.File)
7281 if !ok {
7282 t.Errorf("r.FormFile(%q) returned type %T, want *os.File", key, f)
7283 return
7284 }
7285 w.Write([]byte(of.Name()))
7286 }))
7287
7288 fBuf := new(bytes.Buffer)
7289 mw := multipart.NewWriter(fBuf)
7290 mf, err := mw.CreateFormFile(key, "myfile.txt")
7291 if err != nil {
7292 t.Fatal(err)
7293 }
7294 if _, err := mf.Write(bytes.Repeat([]byte("A"), maxMemory*2)); err != nil {
7295 t.Fatal(err)
7296 }
7297 if err := mw.Close(); err != nil {
7298 t.Fatal(err)
7299 }
7300 req, err := NewRequest("POST", cst.ts.URL, fBuf)
7301 if err != nil {
7302 t.Fatal(err)
7303 }
7304 req.Header.Set("Content-Type", mw.FormDataContentType())
7305 res, err := cst.c.Do(req)
7306 if err != nil {
7307 t.Fatal(err)
7308 }
7309 defer res.Body.Close()
7310 fname, err := io.ReadAll(res.Body)
7311 if err != nil {
7312 t.Fatal(err)
7313 }
7314 cst.close()
7315 if _, err := os.Stat(string(fname)); !errors.Is(err, os.ErrNotExist) {
7316 t.Errorf("file %q exists after HTTP handler returned", string(fname))
7317 }
7318 }
7319
7320 func TestHeadBody(t *testing.T) {
7321 const identityMode = false
7322 const chunkedMode = true
7323 run(t, func(t *testing.T, mode testMode) {
7324 t.Run("identity", func(t *testing.T) { testHeadBody(t, mode, identityMode, "HEAD") })
7325 t.Run("chunked", func(t *testing.T) { testHeadBody(t, mode, chunkedMode, "HEAD") })
7326 })
7327 }
7328
7329 func TestGetBody(t *testing.T) {
7330 const identityMode = false
7331 const chunkedMode = true
7332 run(t, func(t *testing.T, mode testMode) {
7333 t.Run("identity", func(t *testing.T) { testHeadBody(t, mode, identityMode, "GET") })
7334 t.Run("chunked", func(t *testing.T) { testHeadBody(t, mode, chunkedMode, "GET") })
7335 })
7336 }
7337
7338 func testHeadBody(t *testing.T, mode testMode, chunked bool, method string) {
7339 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
7340 b, err := io.ReadAll(r.Body)
7341 if err != nil {
7342 t.Errorf("server reading body: %v", err)
7343 return
7344 }
7345 w.Header().Set("X-Request-Body", string(b))
7346 w.Header().Set("Content-Length", "0")
7347 }))
7348 defer cst.close()
7349 for _, reqBody := range []string{
7350 "",
7351 "",
7352 "request_body",
7353 "",
7354 } {
7355 var bodyReader io.Reader
7356 if reqBody != "" {
7357 bodyReader = strings.NewReader(reqBody)
7358 if chunked {
7359 bodyReader = bufio.NewReader(bodyReader)
7360 }
7361 }
7362 req, err := NewRequest(method, cst.ts.URL, bodyReader)
7363 if err != nil {
7364 t.Fatal(err)
7365 }
7366 res, err := cst.c.Do(req)
7367 if err != nil {
7368 t.Fatal(err)
7369 }
7370 res.Body.Close()
7371 if got, want := res.StatusCode, 200; got != want {
7372 t.Errorf("%v request with %d-byte body: StatusCode = %v, want %v", method, len(reqBody), got, want)
7373 }
7374 if got, want := res.Header.Get("X-Request-Body"), reqBody; got != want {
7375 t.Errorf("%v request with %d-byte body: handler read body %q, want %q", method, len(reqBody), got, want)
7376 }
7377 }
7378 }
7379
7380
7381
7382 func TestDisableContentLength(t *testing.T) { run(t, testDisableContentLength) }
7383 func testDisableContentLength(t *testing.T, mode testMode) {
7384 noCL := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
7385 w.Header()["Content-Length"] = nil
7386 fmt.Fprintf(w, "OK")
7387 }))
7388
7389 res, err := noCL.c.Get(noCL.ts.URL)
7390 if err != nil {
7391 t.Fatal(err)
7392 }
7393 if got, haveCL := res.Header["Content-Length"]; haveCL {
7394 t.Errorf("Unexpected Content-Length: %q", got)
7395 }
7396 if err := res.Body.Close(); err != nil {
7397 t.Fatal(err)
7398 }
7399
7400 withCL := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
7401 fmt.Fprintf(w, "OK")
7402 }))
7403
7404 res, err = withCL.c.Get(withCL.ts.URL)
7405 if err != nil {
7406 t.Fatal(err)
7407 }
7408 if got := res.Header.Get("Content-Length"); got != "2" {
7409 t.Errorf("Content-Length: %q; want 2", got)
7410 }
7411 if err := res.Body.Close(); err != nil {
7412 t.Fatal(err)
7413 }
7414 }
7415
7416 func TestErrorContentLength(t *testing.T) { run(t, testErrorContentLength) }
7417 func testErrorContentLength(t *testing.T, mode testMode) {
7418 const errorBody = "an error occurred"
7419 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
7420 w.Header().Set("Content-Length", "1000")
7421 Error(w, errorBody, 400)
7422 }))
7423 res, err := cst.c.Get(cst.ts.URL)
7424 if err != nil {
7425 t.Fatalf("Get(%q) = %v", cst.ts.URL, err)
7426 }
7427 defer res.Body.Close()
7428 body, err := io.ReadAll(res.Body)
7429 if err != nil {
7430 t.Fatalf("io.ReadAll(res.Body) = %v", err)
7431 }
7432 if string(body) != errorBody+"\n" {
7433 t.Fatalf("read body: %q, want %q", string(body), errorBody)
7434 }
7435 }
7436
7437 func TestError(t *testing.T) {
7438 w := httptest.NewRecorder()
7439 w.Header().Set("Content-Length", "1")
7440 w.Header().Set("X-Content-Type-Options", "scratch and sniff")
7441 w.Header().Set("Other", "foo")
7442 Error(w, "oops", 432)
7443
7444 h := w.Header()
7445 for _, hdr := range []string{"Content-Length"} {
7446 if v, ok := h[hdr]; ok {
7447 t.Errorf("%s: %q, want not present", hdr, v)
7448 }
7449 }
7450 if v := h.Get("Content-Type"); v != "text/plain; charset=utf-8" {
7451 t.Errorf("Content-Type: %q, want %q", v, "text/plain; charset=utf-8")
7452 }
7453 if v := h.Get("X-Content-Type-Options"); v != "nosniff" {
7454 t.Errorf("X-Content-Type-Options: %q, want %q", v, "nosniff")
7455 }
7456 }
7457
7458 func TestServerReadAfterWriteHeader100Continue(t *testing.T) {
7459 run(t, testServerReadAfterWriteHeader100Continue)
7460 }
7461 func testServerReadAfterWriteHeader100Continue(t *testing.T, mode testMode) {
7462 t.Skip("https://go.dev/issue/67555")
7463 body := []byte("body")
7464 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
7465 w.WriteHeader(200)
7466 NewResponseController(w).Flush()
7467 io.ReadAll(r.Body)
7468 w.Write(body)
7469 }), func(tr *Transport) {
7470 tr.ExpectContinueTimeout = 24 * time.Hour
7471 })
7472
7473 req, _ := NewRequest("GET", cst.ts.URL, strings.NewReader("body"))
7474 req.Header.Set("Expect", "100-continue")
7475 res, err := cst.c.Do(req)
7476 if err != nil {
7477 t.Fatalf("Get(%q) = %v", cst.ts.URL, err)
7478 }
7479 defer res.Body.Close()
7480 got, err := io.ReadAll(res.Body)
7481 if err != nil {
7482 t.Fatalf("io.ReadAll(res.Body) = %v", err)
7483 }
7484 if !bytes.Equal(got, body) {
7485 t.Fatalf("response body = %q, want %q", got, body)
7486 }
7487 }
7488
7489 func TestServerReadAfterHandlerDone100Continue(t *testing.T) {
7490 run(t, testServerReadAfterHandlerDone100Continue)
7491 }
7492 func testServerReadAfterHandlerDone100Continue(t *testing.T, mode testMode) {
7493 t.Skip("https://go.dev/issue/67555")
7494 readyc := make(chan struct{})
7495 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
7496 go func() {
7497 <-readyc
7498 io.ReadAll(r.Body)
7499 <-readyc
7500 }()
7501 }), func(tr *Transport) {
7502 tr.ExpectContinueTimeout = 24 * time.Hour
7503 })
7504
7505 req, _ := NewRequest("GET", cst.ts.URL, strings.NewReader("body"))
7506 req.Header.Set("Expect", "100-continue")
7507 res, err := cst.c.Do(req)
7508 if err != nil {
7509 t.Fatalf("Get(%q) = %v", cst.ts.URL, err)
7510 }
7511 res.Body.Close()
7512 readyc <- struct{}{}
7513 readyc <- struct{}{}
7514 }
7515
7516 func TestServerReadAfterHandlerAbort100Continue(t *testing.T) {
7517 run(t, testServerReadAfterHandlerAbort100Continue)
7518 }
7519 func testServerReadAfterHandlerAbort100Continue(t *testing.T, mode testMode) {
7520 t.Skip("https://go.dev/issue/67555")
7521 readyc := make(chan struct{})
7522 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
7523 go func() {
7524 <-readyc
7525 io.ReadAll(r.Body)
7526 <-readyc
7527 }()
7528 panic(ErrAbortHandler)
7529 }), func(tr *Transport) {
7530 tr.ExpectContinueTimeout = 24 * time.Hour
7531 })
7532
7533 req, _ := NewRequest("GET", cst.ts.URL, strings.NewReader("body"))
7534 req.Header.Set("Expect", "100-continue")
7535 res, err := cst.c.Do(req)
7536 if err == nil {
7537 res.Body.Close()
7538 }
7539 readyc <- struct{}{}
7540 readyc <- struct{}{}
7541 }
7542
7543 func TestInvalidChunkedBodies(t *testing.T) {
7544 for _, test := range []struct {
7545 name string
7546 b string
7547 }{{
7548 name: "bare LF in chunk size",
7549 b: "1\na\r\n0\r\n\r\n",
7550 }, {
7551 name: "bare LF at body end",
7552 b: "1\r\na\r\n0\r\n\n",
7553 }} {
7554 t.Run(test.name, func(t *testing.T) {
7555 reqc := make(chan error)
7556 ts := newClientServerTest(t, http1Mode, HandlerFunc(func(w ResponseWriter, r *Request) {
7557 got, err := io.ReadAll(r.Body)
7558 if err == nil {
7559 t.Logf("read body: %q", got)
7560 }
7561 reqc <- err
7562 })).ts
7563
7564 serverURL, err := url.Parse(ts.URL)
7565 if err != nil {
7566 t.Fatal(err)
7567 }
7568
7569 conn, err := net.Dial("tcp", serverURL.Host)
7570 if err != nil {
7571 t.Fatal(err)
7572 }
7573
7574 if _, err := conn.Write([]byte(
7575 "POST / HTTP/1.1\r\n" +
7576 "Host: localhost\r\n" +
7577 "Transfer-Encoding: chunked\r\n" +
7578 "Connection: close\r\n" +
7579 "\r\n" +
7580 test.b)); err != nil {
7581 t.Fatal(err)
7582 }
7583 conn.(*net.TCPConn).CloseWrite()
7584
7585 if err := <-reqc; err == nil {
7586 t.Errorf("server handler: io.ReadAll(r.Body) succeeded, want error")
7587 }
7588 })
7589 }
7590 }
7591
7592
7593 func TestServerTLSNextProtos(t *testing.T) {
7594 run(t, testServerTLSNextProtos, []testMode{https1Mode, http2Mode})
7595 }
7596 func testServerTLSNextProtos(t *testing.T, mode testMode) {
7597 CondSkipHTTP2(t)
7598
7599 cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey)
7600 if err != nil {
7601 t.Fatal(err)
7602 }
7603 leafCert, err := x509.ParseCertificate(cert.Certificate[0])
7604 if err != nil {
7605 t.Fatal(err)
7606 }
7607 certpool := x509.NewCertPool()
7608 certpool.AddCert(leafCert)
7609
7610 protos := new(Protocols)
7611 switch mode {
7612 case https1Mode:
7613 protos.SetHTTP1(true)
7614 case http2Mode:
7615 protos.SetHTTP2(true)
7616 }
7617
7618 wantNextProtos := []string{"http/1.1", "h2", "other"}
7619 nextProtos := slices.Clone(wantNextProtos)
7620
7621
7622 srv := &Server{
7623 TLSConfig: &tls.Config{
7624 Certificates: []tls.Certificate{cert},
7625 NextProtos: nextProtos,
7626 },
7627 Handler: HandlerFunc(func(w ResponseWriter, req *Request) {}),
7628 Protocols: protos,
7629 }
7630 tr := &Transport{
7631 TLSClientConfig: &tls.Config{
7632 RootCAs: certpool,
7633 NextProtos: nextProtos,
7634 },
7635 Protocols: protos,
7636 }
7637
7638 listener := newLocalListener(t)
7639 srvc := make(chan error, 1)
7640 go func() {
7641 srvc <- srv.ServeTLS(listener, "", "")
7642 }()
7643 t.Cleanup(func() {
7644 srv.Close()
7645 <-srvc
7646 })
7647
7648 client := &Client{Transport: tr}
7649 resp, err := client.Get("https://" + listener.Addr().String())
7650 if err != nil {
7651 t.Fatal(err)
7652 }
7653 resp.Body.Close()
7654
7655 if !slices.Equal(nextProtos, wantNextProtos) {
7656 t.Fatalf("after running test: original NextProtos slice = %v, want %v", nextProtos, wantNextProtos)
7657 }
7658 }
7659
View as plain text