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