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 for _, tt := range tests {
3482 t.Run(tt.name, func(t *testing.T) {
3483 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
3484 w.WriteHeader(StatusOK)
3485 }), func(s *Server) {
3486 s.MaxHeaderValueCount = tt.limit
3487 }, optQuietLog)
3488
3489 req, _ := NewRequest("GET", cst.ts.URL, nil)
3490 tt.setup(req)
3491
3492 res, err := cst.c.Do(req)
3493 if err != nil {
3494 t.Fatal(err)
3495 }
3496 defer res.Body.Close()
3497 if res.StatusCode != tt.wantStatus {
3498 t.Errorf("got status %d, want %d", res.StatusCode, tt.wantStatus)
3499 }
3500 })
3501 }
3502 }
3503
3504 func TestRequestTrailerHeaderValueCountLimit(t *testing.T) {
3505 run(t, testRequestTrailerHeaderValueCountLimit, http3SkippedMode)
3506 }
3507 func testRequestTrailerHeaderValueCountLimit(t *testing.T, mode testMode) {
3508 tests := []struct {
3509 name string
3510 limit int
3511 setup func(req *Request)
3512 wantErr bool
3513 }{
3514 {
3515 name: "below limit",
3516 limit: 15,
3517 setup: func(req *Request) {
3518 req.Trailer = make(Header)
3519 for i := range 14 {
3520 req.Trailer.Add(fmt.Sprintf("X-Trailer-%d", i), "val")
3521 }
3522 },
3523 },
3524 {
3525 name: "above limit",
3526 limit: 15,
3527 setup: func(req *Request) {
3528 req.Trailer = make(Header)
3529 for i := range 16 {
3530 req.Trailer.Add(fmt.Sprintf("X-Trailer-%d", i), "val")
3531 }
3532 },
3533 wantErr: true,
3534 },
3535 {
3536 name: "comma separated values count as one",
3537 limit: 15,
3538 setup: func(req *Request) {
3539 req.Trailer = make(Header)
3540 vals := make([]string, 16)
3541 for i := range vals {
3542 vals[i] = "val"
3543 }
3544 req.Trailer.Add("X-Comma-Trailer", strings.Join(vals, ", "))
3545 },
3546 },
3547 {
3548 name: "multiple values count as multiple",
3549 limit: 15,
3550 setup: func(req *Request) {
3551 req.Trailer = make(Header)
3552 for range 16 {
3553 req.Trailer.Add("X-Repeated-Trailer", "val")
3554 }
3555 },
3556 wantErr: true,
3557 },
3558 }
3559 for _, tt := range tests {
3560 t.Run(tt.name, func(t *testing.T) {
3561 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
3562 _, err := io.Copy(io.Discard, r.Body)
3563 if (err != nil) != tt.wantErr {
3564 t.Errorf("Read = %v, want %v", err, tt.wantErr)
3565 }
3566 }), func(s *Server) {
3567 s.MaxHeaderValueCount = tt.limit
3568 }, optQuietLog)
3569
3570 req, _ := NewRequest("GET", cst.ts.URL, strings.NewReader("some body"))
3571 req.TransferEncoding = []string{"chunked"}
3572 tt.setup(req)
3573
3574
3575
3576 res, err := cst.c.Do(req)
3577 if err != nil && !tt.wantErr {
3578 t.Fatalf("unexpected Do error: %v", err)
3579 }
3580 if err == nil {
3581 res.Body.Close()
3582 }
3583 })
3584 }
3585 }
3586
3587 type neverEnding byte
3588
3589 func (b neverEnding) Read(p []byte) (n int, err error) {
3590 for i := range p {
3591 p[i] = byte(b)
3592 }
3593 return len(p), nil
3594 }
3595
3596 type bodyLimitReader struct {
3597 mu sync.Mutex
3598 count int
3599 limit int
3600 closed chan struct{}
3601 }
3602
3603 func (r *bodyLimitReader) Read(p []byte) (int, error) {
3604 r.mu.Lock()
3605 defer r.mu.Unlock()
3606 select {
3607 case <-r.closed:
3608 return 0, errors.New("closed")
3609 default:
3610 }
3611 if r.count > r.limit {
3612 return 0, errors.New("at limit")
3613 }
3614 r.count += len(p)
3615 for i := range p {
3616 p[i] = 'a'
3617 }
3618 return len(p), nil
3619 }
3620
3621 func (r *bodyLimitReader) Close() error {
3622 r.mu.Lock()
3623 defer r.mu.Unlock()
3624 close(r.closed)
3625 return nil
3626 }
3627
3628 func TestRequestBodyLimit(t *testing.T) { run(t, testRequestBodyLimit) }
3629 func testRequestBodyLimit(t *testing.T, mode testMode) {
3630 const limit = 1 << 20
3631 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
3632 r.Body = MaxBytesReader(w, r.Body, limit)
3633 n, err := io.Copy(io.Discard, r.Body)
3634 if err == nil {
3635 t.Errorf("expected error from io.Copy")
3636 }
3637 if n != limit {
3638 t.Errorf("io.Copy = %d, want %d", n, limit)
3639 }
3640 mbErr, ok := err.(*MaxBytesError)
3641 if !ok {
3642 t.Errorf("expected MaxBytesError, got %T", err)
3643 }
3644 if mbErr.Limit != limit {
3645 t.Errorf("MaxBytesError.Limit = %d, want %d", mbErr.Limit, limit)
3646 }
3647 }))
3648
3649 body := &bodyLimitReader{
3650 closed: make(chan struct{}),
3651 limit: limit * 200,
3652 }
3653 req, _ := NewRequest("POST", cst.ts.URL, body)
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664 resp, err := cst.c.Do(req)
3665 if err == nil {
3666 resp.Body.Close()
3667 }
3668
3669
3670 <-body.closed
3671
3672 if body.count > limit*100 {
3673 t.Errorf("handler restricted the request body to %d bytes, but client managed to write %d",
3674 limit, body.count)
3675 }
3676 }
3677
3678
3679
3680 func TestClientWriteShutdown(t *testing.T) { run(t, testClientWriteShutdown, http3SkippedMode) }
3681 func testClientWriteShutdown(t *testing.T, mode testMode) {
3682 if runtime.GOOS == "plan9" {
3683 t.Skip("skipping test; see https://golang.org/issue/17906")
3684 }
3685 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {})).ts
3686 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
3687 if err != nil {
3688 t.Fatalf("Dial: %v", err)
3689 }
3690 err = conn.(*net.TCPConn).CloseWrite()
3691 if err != nil {
3692 t.Fatalf("CloseWrite: %v", err)
3693 }
3694
3695 bs, err := io.ReadAll(conn)
3696 if err != nil {
3697 t.Errorf("ReadAll: %v", err)
3698 }
3699 got := string(bs)
3700 if got != "" {
3701 t.Errorf("read %q from server; want nothing", got)
3702 }
3703 }
3704
3705
3706
3707 func TestServerBufferedChunking(t *testing.T) {
3708 conn := new(testConn)
3709 conn.readBuf.Write([]byte("GET / HTTP/1.1\r\nHost: foo\r\n\r\n"))
3710 conn.closec = make(chan bool, 1)
3711 ls := &oneConnListener{conn}
3712 go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
3713 rw.(Flusher).Flush()
3714 rw.Write([]byte{'x'})
3715 rw.Write([]byte{'y'})
3716 rw.Write([]byte{'z'})
3717 }))
3718 <-conn.closec
3719 if !bytes.HasSuffix(conn.writeBuf.Bytes(), []byte("\r\n\r\n3\r\nxyz\r\n0\r\n\r\n")) {
3720 t.Errorf("response didn't end with a single 3 byte 'xyz' chunk; got:\n%q",
3721 conn.writeBuf.Bytes())
3722 }
3723 }
3724
3725
3726
3727
3728
3729 func TestServerGracefulClose(t *testing.T) {
3730
3731 run(t, testServerGracefulClose, []testMode{http1Mode}, testNotParallel)
3732 }
3733 func testServerGracefulClose(t *testing.T, mode testMode) {
3734 runTimeSensitiveTest(t, []time.Duration{
3735 1 * time.Millisecond,
3736 5 * time.Millisecond,
3737 10 * time.Millisecond,
3738 50 * time.Millisecond,
3739 100 * time.Millisecond,
3740 500 * time.Millisecond,
3741 time.Second,
3742 5 * time.Second,
3743 }, func(t *testing.T, timeout time.Duration) error {
3744 SetRSTAvoidanceDelay(t, timeout)
3745 t.Logf("set RST avoidance delay to %v", timeout)
3746
3747 const bodySize = 5 << 20
3748 req := []byte(fmt.Sprintf("POST / HTTP/1.1\r\nHost: foo.com\r\nContent-Length: %d\r\n\r\n", bodySize))
3749 for i := 0; i < bodySize; i++ {
3750 req = append(req, 'x')
3751 }
3752
3753 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
3754 Error(w, "bye", StatusUnauthorized)
3755 }))
3756
3757
3758 defer cst.close()
3759 ts := cst.ts
3760
3761 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
3762 if err != nil {
3763 return err
3764 }
3765 writeErr := make(chan error)
3766 go func() {
3767 _, err := conn.Write(req)
3768 writeErr <- err
3769 }()
3770 defer func() {
3771 conn.Close()
3772
3773
3774
3775 <-writeErr
3776 }()
3777
3778 br := bufio.NewReader(conn)
3779 lineNum := 0
3780 for {
3781 line, err := br.ReadString('\n')
3782 if err == io.EOF {
3783 break
3784 }
3785 if err != nil {
3786 return fmt.Errorf("ReadLine: %v", err)
3787 }
3788 lineNum++
3789 if lineNum == 1 && !strings.Contains(line, "401 Unauthorized") {
3790 t.Errorf("Response line = %q; want a 401", line)
3791 }
3792 }
3793 return nil
3794 })
3795 }
3796
3797 func TestCaseSensitiveMethod(t *testing.T) { run(t, testCaseSensitiveMethod) }
3798 func testCaseSensitiveMethod(t *testing.T, mode testMode) {
3799 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
3800 if r.Method != "get" {
3801 t.Errorf(`Got method %q; want "get"`, r.Method)
3802 }
3803 }))
3804 defer cst.close()
3805 req, _ := NewRequest("get", cst.ts.URL, nil)
3806 res, err := cst.c.Do(req)
3807 if err != nil {
3808 t.Error(err)
3809 return
3810 }
3811
3812 res.Body.Close()
3813 }
3814
3815
3816
3817
3818
3819 func TestContentLengthZero(t *testing.T) {
3820 run(t, testContentLengthZero, []testMode{http1Mode})
3821 }
3822 func testContentLengthZero(t *testing.T, mode testMode) {
3823 ts := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {})).ts
3824
3825 for _, version := range []string{"HTTP/1.0", "HTTP/1.1"} {
3826 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
3827 if err != nil {
3828 t.Fatalf("error dialing: %v", err)
3829 }
3830 _, err = fmt.Fprintf(conn, "GET / %v\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n", version)
3831 if err != nil {
3832 t.Fatalf("error writing: %v", err)
3833 }
3834 req, _ := NewRequest("GET", "/", nil)
3835 res, err := ReadResponse(bufio.NewReader(conn), req)
3836 if err != nil {
3837 t.Fatalf("error reading response: %v", err)
3838 }
3839 if te := res.TransferEncoding; len(te) > 0 {
3840 t.Errorf("For version %q, Transfer-Encoding = %q; want none", version, te)
3841 }
3842 if cl := res.ContentLength; cl != 0 {
3843 t.Errorf("For version %q, Content-Length = %v; want 0", version, cl)
3844 }
3845 conn.Close()
3846 }
3847 }
3848
3849 func TestCloseNotifier(t *testing.T) {
3850 run(t, testCloseNotifier, []testMode{http1Mode})
3851 }
3852 func testCloseNotifier(t *testing.T, mode testMode) {
3853 gotReq := make(chan bool, 1)
3854 sawClose := make(chan bool, 1)
3855 ts := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
3856 gotReq <- true
3857 cc := rw.(CloseNotifier).CloseNotify()
3858 <-cc
3859 sawClose <- true
3860 })).ts
3861 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
3862 if err != nil {
3863 t.Fatalf("error dialing: %v", err)
3864 }
3865 diec := make(chan bool)
3866 go func() {
3867 _, err = fmt.Fprintf(conn, "GET / HTTP/1.1\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n")
3868 if err != nil {
3869 t.Error(err)
3870 return
3871 }
3872 <-diec
3873 conn.Close()
3874 }()
3875 For:
3876 for {
3877 select {
3878 case <-gotReq:
3879 diec <- true
3880 case <-sawClose:
3881 break For
3882 }
3883 }
3884 ts.Close()
3885 }
3886
3887
3888
3889
3890
3891 func TestCloseNotifierPipelined(t *testing.T) {
3892 run(t, testCloseNotifierPipelined, []testMode{http1Mode})
3893 }
3894 func testCloseNotifierPipelined(t *testing.T, mode testMode) {
3895 gotReq := make(chan bool, 2)
3896 sawClose := make(chan bool, 2)
3897 ts := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
3898 gotReq <- true
3899 cc := rw.(CloseNotifier).CloseNotify()
3900 select {
3901 case <-cc:
3902 t.Error("unexpected CloseNotify")
3903 case <-time.After(100 * time.Millisecond):
3904 }
3905 sawClose <- true
3906 })).ts
3907 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
3908 if err != nil {
3909 t.Fatalf("error dialing: %v", err)
3910 }
3911 diec := make(chan bool, 1)
3912 defer close(diec)
3913 go func() {
3914 const req = "GET / HTTP/1.1\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n"
3915 _, err = io.WriteString(conn, req+req)
3916 if err != nil {
3917 t.Error(err)
3918 return
3919 }
3920 <-diec
3921 conn.Close()
3922 }()
3923 reqs := 0
3924 closes := 0
3925 for {
3926 select {
3927 case <-gotReq:
3928 reqs++
3929 if reqs > 2 {
3930 t.Fatal("too many requests")
3931 }
3932 case <-sawClose:
3933 closes++
3934 if closes > 1 {
3935 return
3936 }
3937 }
3938 }
3939 }
3940
3941 func TestCloseNotifierChanLeak(t *testing.T) {
3942 defer afterTest(t)
3943 req := reqBytes("GET / HTTP/1.0\nHost: golang.org")
3944 for i := 0; i < 20; i++ {
3945 var output bytes.Buffer
3946 conn := &rwTestConn{
3947 Reader: bytes.NewReader(req),
3948 Writer: &output,
3949 closec: make(chan bool, 1),
3950 }
3951 ln := &oneConnListener{conn: conn}
3952 handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
3953
3954
3955
3956 _ = rw.(CloseNotifier).CloseNotify()
3957 })
3958 go Serve(ln, handler)
3959 <-conn.closec
3960 }
3961 }
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972 func TestHijackAfterCloseNotifier(t *testing.T) {
3973 run(t, testHijackAfterCloseNotifier, []testMode{http1Mode})
3974 }
3975 func testHijackAfterCloseNotifier(t *testing.T, mode testMode) {
3976 script := make(chan string, 2)
3977 script <- "closenotify"
3978 script <- "hijack"
3979 close(script)
3980 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
3981 plan := <-script
3982 switch plan {
3983 default:
3984 panic("bogus plan; too many requests")
3985 case "closenotify":
3986 w.(CloseNotifier).CloseNotify()
3987 w.Header().Set("X-Addr", r.RemoteAddr)
3988 case "hijack":
3989 c, _, err := w.(Hijacker).Hijack()
3990 if err != nil {
3991 t.Errorf("Hijack in Handler: %v", err)
3992 return
3993 }
3994 if _, ok := c.(*net.TCPConn); !ok {
3995
3996
3997 t.Errorf("type of hijacked conn is %T; want *net.TCPConn", c)
3998 }
3999 fmt.Fprintf(c, "HTTP/1.0 200 OK\r\nX-Addr: %v\r\nContent-Length: 0\r\n\r\n", r.RemoteAddr)
4000 c.Close()
4001 return
4002 }
4003 })).ts
4004 res1, err := ts.Client().Get(ts.URL)
4005 if err != nil {
4006 log.Fatal(err)
4007 }
4008 res2, err := ts.Client().Get(ts.URL)
4009 if err != nil {
4010 log.Fatal(err)
4011 }
4012 addr1 := res1.Header.Get("X-Addr")
4013 addr2 := res2.Header.Get("X-Addr")
4014 if addr1 == "" || addr1 != addr2 {
4015 t.Errorf("addr1, addr2 = %q, %q; want same", addr1, addr2)
4016 }
4017 }
4018
4019 func TestHijackBeforeRequestBodyRead(t *testing.T) {
4020 run(t, testHijackBeforeRequestBodyRead, []testMode{http1Mode})
4021 }
4022 func testHijackBeforeRequestBodyRead(t *testing.T, mode testMode) {
4023 var requestBody = bytes.Repeat([]byte("a"), 1<<20)
4024 bodyOkay := make(chan bool, 1)
4025 gotCloseNotify := make(chan bool, 1)
4026 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
4027 defer close(bodyOkay)
4028
4029 reqBody := r.Body
4030 r.Body = nil
4031
4032 gone := w.(CloseNotifier).CloseNotify()
4033 slurp, err := io.ReadAll(reqBody)
4034 if err != nil {
4035 t.Errorf("Body read: %v", err)
4036 return
4037 }
4038 if len(slurp) != len(requestBody) {
4039 t.Errorf("Backend read %d request body bytes; want %d", len(slurp), len(requestBody))
4040 return
4041 }
4042 if !bytes.Equal(slurp, requestBody) {
4043 t.Error("Backend read wrong request body.")
4044 return
4045 }
4046 bodyOkay <- true
4047 <-gone
4048 gotCloseNotify <- true
4049 })).ts
4050
4051 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
4052 if err != nil {
4053 t.Fatal(err)
4054 }
4055 defer conn.Close()
4056
4057 fmt.Fprintf(conn, "POST / HTTP/1.1\r\nHost: foo\r\nContent-Length: %d\r\n\r\n%s",
4058 len(requestBody), requestBody)
4059 if !<-bodyOkay {
4060
4061 return
4062 }
4063 conn.Close()
4064 <-gotCloseNotify
4065 }
4066
4067 func TestOptions(t *testing.T) { run(t, testOptions, []testMode{http1Mode}) }
4068 func testOptions(t *testing.T, mode testMode) {
4069 uric := make(chan string, 2)
4070 mux := NewServeMux()
4071 mux.HandleFunc("/", func(w ResponseWriter, r *Request) {
4072 uric <- r.RequestURI
4073 })
4074 ts := newClientServerTest(t, mode, mux).ts
4075
4076 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
4077 if err != nil {
4078 t.Fatal(err)
4079 }
4080 defer conn.Close()
4081
4082
4083 _, err = conn.Write([]byte("OPTIONS * HTTP/1.1\r\nHost: foo.com\r\n\r\n"))
4084 if err != nil {
4085 t.Fatal(err)
4086 }
4087 br := bufio.NewReader(conn)
4088 res, err := ReadResponse(br, &Request{Method: "OPTIONS"})
4089 if err != nil {
4090 t.Fatal(err)
4091 }
4092 if res.StatusCode != 200 {
4093 t.Errorf("Got non-200 response to OPTIONS *: %#v", res)
4094 }
4095
4096
4097 _, err = conn.Write([]byte("GET * HTTP/1.1\r\nHost: foo.com\r\n\r\n"))
4098 if err != nil {
4099 t.Fatal(err)
4100 }
4101 res, err = ReadResponse(br, &Request{Method: "GET"})
4102 if err != nil {
4103 t.Fatal(err)
4104 }
4105 if res.StatusCode != 400 {
4106 t.Errorf("Got non-400 response to GET *: %#v", res)
4107 }
4108
4109 res, err = Get(ts.URL + "/second")
4110 if err != nil {
4111 t.Fatal(err)
4112 }
4113 res.Body.Close()
4114 if got := <-uric; got != "/second" {
4115 t.Errorf("Handler saw request for %q; want /second", got)
4116 }
4117 }
4118
4119 func TestOptionsHandler(t *testing.T) { run(t, testOptionsHandler, []testMode{http1Mode}) }
4120 func testOptionsHandler(t *testing.T, mode testMode) {
4121 rc := make(chan *Request, 1)
4122
4123 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
4124 rc <- r
4125 }), func(ts *httptest.Server) {
4126 ts.Config.DisableGeneralOptionsHandler = true
4127 }).ts
4128
4129 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
4130 if err != nil {
4131 t.Fatal(err)
4132 }
4133 defer conn.Close()
4134
4135 _, err = conn.Write([]byte("OPTIONS * HTTP/1.1\r\nHost: foo.com\r\n\r\n"))
4136 if err != nil {
4137 t.Fatal(err)
4138 }
4139
4140 if got := <-rc; got.Method != "OPTIONS" || got.RequestURI != "*" {
4141 t.Errorf("Expected OPTIONS * request, got %v", got)
4142 }
4143 }
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154 func TestHeaderToWire(t *testing.T) {
4155 tests := []struct {
4156 name string
4157 handler func(ResponseWriter, *Request)
4158 check func(got, logs string) error
4159 }{
4160 {
4161 name: "write without Header",
4162 handler: func(rw ResponseWriter, r *Request) {
4163 rw.Write([]byte("hello world"))
4164 },
4165 check: func(got, logs string) error {
4166 if !strings.Contains(got, "Content-Length:") {
4167 return errors.New("no content-length")
4168 }
4169 if !strings.Contains(got, "Content-Type: text/plain") {
4170 return errors.New("no content-type")
4171 }
4172 return nil
4173 },
4174 },
4175 {
4176 name: "Header mutation before write",
4177 handler: func(rw ResponseWriter, r *Request) {
4178 h := rw.Header()
4179 h.Set("Content-Type", "some/type")
4180 rw.Write([]byte("hello world"))
4181 h.Set("Too-Late", "bogus")
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: some/type") {
4188 return errors.New("wrong content-type")
4189 }
4190 if strings.Contains(got, "Too-Late") {
4191 return errors.New("don't want too-late header")
4192 }
4193 return nil
4194 },
4195 },
4196 {
4197 name: "write then useless Header mutation",
4198 handler: func(rw ResponseWriter, r *Request) {
4199 rw.Write([]byte("hello world"))
4200 rw.Header().Set("Too-Late", "Write already wrote headers")
4201 },
4202 check: func(got, logs string) error {
4203 if strings.Contains(got, "Too-Late") {
4204 return errors.New("header appeared from after WriteHeader")
4205 }
4206 return nil
4207 },
4208 },
4209 {
4210 name: "flush then write",
4211 handler: func(rw ResponseWriter, r *Request) {
4212 rw.(Flusher).Flush()
4213 rw.Write([]byte("post-flush"))
4214 rw.Header().Set("Too-Late", "Write already wrote headers")
4215 },
4216 check: func(got, logs string) error {
4217 if !strings.Contains(got, "Transfer-Encoding: chunked") {
4218 return errors.New("not chunked")
4219 }
4220 if strings.Contains(got, "Too-Late") {
4221 return errors.New("header appeared from after WriteHeader")
4222 }
4223 return nil
4224 },
4225 },
4226 {
4227 name: "header then flush",
4228 handler: func(rw ResponseWriter, r *Request) {
4229 rw.Header().Set("Content-Type", "some/type")
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 if !strings.Contains(got, "Content-Type: some/type") {
4242 return errors.New("wrong content-type")
4243 }
4244 return nil
4245 },
4246 },
4247 {
4248 name: "sniff-on-first-write content-type",
4249 handler: func(rw ResponseWriter, r *Request) {
4250 rw.Write([]byte("<html><head></head><body>some html</body></html>"))
4251 rw.Header().Set("Content-Type", "x/wrong")
4252 },
4253 check: func(got, logs string) error {
4254 if !strings.Contains(got, "Content-Type: text/html") {
4255 return errors.New("wrong content-type; want html")
4256 }
4257 return nil
4258 },
4259 },
4260 {
4261 name: "explicit content-type wins",
4262 handler: func(rw ResponseWriter, r *Request) {
4263 rw.Header().Set("Content-Type", "some/type")
4264 rw.Write([]byte("<html><head></head><body>some html</body></html>"))
4265 },
4266 check: func(got, logs string) error {
4267 if !strings.Contains(got, "Content-Type: some/type") {
4268 return errors.New("wrong content-type; want html")
4269 }
4270 return nil
4271 },
4272 },
4273 {
4274 name: "empty handler",
4275 handler: func(rw ResponseWriter, r *Request) {
4276 },
4277 check: func(got, logs string) error {
4278 if !strings.Contains(got, "Content-Length: 0") {
4279 return errors.New("want 0 content-length")
4280 }
4281 return nil
4282 },
4283 },
4284 {
4285 name: "only Header, no write",
4286 handler: func(rw ResponseWriter, r *Request) {
4287 rw.Header().Set("Some-Header", "some-value")
4288 },
4289 check: func(got, logs string) error {
4290 if !strings.Contains(got, "Some-Header") {
4291 return errors.New("didn't get header")
4292 }
4293 return nil
4294 },
4295 },
4296 {
4297 name: "WriteHeader call",
4298 handler: func(rw ResponseWriter, r *Request) {
4299 rw.WriteHeader(404)
4300 rw.Header().Set("Too-Late", "some-value")
4301 },
4302 check: func(got, logs string) error {
4303 if !strings.Contains(got, "404") {
4304 return errors.New("wrong status")
4305 }
4306 if strings.Contains(got, "Too-Late") {
4307 return errors.New("shouldn't have seen Too-Late")
4308 }
4309 return nil
4310 },
4311 },
4312 }
4313 for _, tc := range tests {
4314 ht := newHandlerTest(HandlerFunc(tc.handler))
4315 got := ht.rawResponse("GET / HTTP/1.1\nHost: golang.org")
4316 logs := ht.logbuf.String()
4317 if err := tc.check(got, logs); err != nil {
4318 t.Errorf("%s: %v\nGot response:\n%s\n\n%s", tc.name, err, got, logs)
4319 }
4320 }
4321 }
4322
4323 type errorListener struct {
4324 errs []error
4325 }
4326
4327 func (l *errorListener) Accept() (c net.Conn, err error) {
4328 if len(l.errs) == 0 {
4329 return nil, io.EOF
4330 }
4331 err = l.errs[0]
4332 l.errs = l.errs[1:]
4333 return
4334 }
4335
4336 func (l *errorListener) Close() error {
4337 return nil
4338 }
4339
4340 func (l *errorListener) Addr() net.Addr {
4341 return dummyAddr("test-address")
4342 }
4343
4344 func TestAcceptMaxFds(t *testing.T) {
4345 setParallel(t)
4346
4347 ln := &errorListener{[]error{
4348 &net.OpError{
4349 Op: "accept",
4350 Err: syscall.EMFILE,
4351 }}}
4352 server := &Server{
4353 Handler: HandlerFunc(HandlerFunc(func(ResponseWriter, *Request) {})),
4354 ErrorLog: log.New(io.Discard, "", 0),
4355 }
4356 err := server.Serve(ln)
4357 if err != io.EOF {
4358 t.Errorf("got error %v, want EOF", err)
4359 }
4360 }
4361
4362 func TestWriteAfterHijack(t *testing.T) {
4363 req := reqBytes("GET / HTTP/1.1\nHost: golang.org")
4364 var buf strings.Builder
4365 wrotec := make(chan bool, 1)
4366 conn := &rwTestConn{
4367 Reader: bytes.NewReader(req),
4368 Writer: &buf,
4369 closec: make(chan bool, 1),
4370 }
4371 handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
4372 conn, bufrw, err := rw.(Hijacker).Hijack()
4373 if err != nil {
4374 t.Error(err)
4375 return
4376 }
4377 go func() {
4378 bufrw.Write([]byte("[hijack-to-bufw]"))
4379 bufrw.Flush()
4380 conn.Write([]byte("[hijack-to-conn]"))
4381 conn.Close()
4382 wrotec <- true
4383 }()
4384 })
4385 ln := &oneConnListener{conn: conn}
4386 go Serve(ln, handler)
4387 <-conn.closec
4388 <-wrotec
4389 if g, w := buf.String(), "[hijack-to-bufw][hijack-to-conn]"; g != w {
4390 t.Errorf("wrote %q; want %q", g, w)
4391 }
4392 }
4393
4394 func TestDoubleHijack(t *testing.T) {
4395 req := reqBytes("GET / HTTP/1.1\nHost: golang.org")
4396 var buf bytes.Buffer
4397 conn := &rwTestConn{
4398 Reader: bytes.NewReader(req),
4399 Writer: &buf,
4400 closec: make(chan bool, 1),
4401 }
4402 handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
4403 conn, _, err := rw.(Hijacker).Hijack()
4404 if err != nil {
4405 t.Error(err)
4406 return
4407 }
4408 _, _, err = rw.(Hijacker).Hijack()
4409 if err == nil {
4410 t.Errorf("got err = nil; want err != nil")
4411 }
4412 conn.Close()
4413 })
4414 ln := &oneConnListener{conn: conn}
4415 go Serve(ln, handler)
4416 <-conn.closec
4417 }
4418
4419
4420
4421
4422
4423
4424
4425 func TestHTTP10ConnectionHeader(t *testing.T) {
4426 run(t, testHTTP10ConnectionHeader, []testMode{http1Mode})
4427 }
4428 func testHTTP10ConnectionHeader(t *testing.T, mode testMode) {
4429 mux := NewServeMux()
4430 mux.Handle("/", HandlerFunc(func(ResponseWriter, *Request) {}))
4431 ts := newClientServerTest(t, mode, mux).ts
4432
4433
4434 tests := []struct {
4435 req string
4436 expect []string
4437 }{
4438 {
4439 req: "GET / HTTP/1.0\r\n\r\n",
4440 expect: nil,
4441 },
4442 {
4443 req: "OPTIONS * HTTP/1.0\r\n\r\n",
4444 expect: nil,
4445 },
4446 {
4447 req: "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n",
4448 expect: []string{"keep-alive"},
4449 },
4450 }
4451
4452 for _, tt := range tests {
4453 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
4454 if err != nil {
4455 t.Fatal("dial err:", err)
4456 }
4457
4458 _, err = fmt.Fprint(conn, tt.req)
4459 if err != nil {
4460 t.Fatal("conn write err:", err)
4461 }
4462
4463 resp, err := ReadResponse(bufio.NewReader(conn), &Request{Method: "GET"})
4464 if err != nil {
4465 t.Fatal("ReadResponse err:", err)
4466 }
4467 conn.Close()
4468 resp.Body.Close()
4469
4470 got := resp.Header["Connection"]
4471 if !slices.Equal(got, tt.expect) {
4472 t.Errorf("wrong Connection headers for request %q. Got %q expect %q", tt.req, got, tt.expect)
4473 }
4474 }
4475 }
4476
4477
4478 func TestServerReaderFromOrder(t *testing.T) { run(t, testServerReaderFromOrder) }
4479 func testServerReaderFromOrder(t *testing.T, mode testMode) {
4480 pr, pw := io.Pipe()
4481 const size = 3 << 20
4482 cst := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
4483 rw.Header().Set("Content-Type", "text/plain")
4484 done := make(chan bool)
4485 go func() {
4486 io.Copy(rw, pr)
4487 close(done)
4488 }()
4489 time.Sleep(25 * time.Millisecond)
4490 n, err := io.Copy(io.Discard, req.Body)
4491 if err != nil {
4492 t.Errorf("handler Copy: %v", err)
4493 return
4494 }
4495 if n != size {
4496 t.Errorf("handler Copy = %d; want %d", n, size)
4497 }
4498 pw.Write([]byte("hi"))
4499 pw.Close()
4500 <-done
4501 }))
4502
4503 req, err := NewRequest("POST", cst.ts.URL, io.LimitReader(neverEnding('a'), size))
4504 if err != nil {
4505 t.Fatal(err)
4506 }
4507 res, err := cst.c.Do(req)
4508 if err != nil {
4509 t.Fatal(err)
4510 }
4511 all, err := io.ReadAll(res.Body)
4512 if err != nil {
4513 t.Fatal(err)
4514 }
4515 res.Body.Close()
4516 if string(all) != "hi" {
4517 t.Errorf("Body = %q; want hi", all)
4518 }
4519 }
4520
4521
4522 func TestCodesPreventingContentTypeAndBody(t *testing.T) {
4523 for _, code := range []int{StatusNotModified, StatusNoContent} {
4524 ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
4525 if r.URL.Path == "/header" {
4526 w.Header().Set("Content-Length", "123")
4527 }
4528 w.WriteHeader(code)
4529 if r.URL.Path == "/more" {
4530 w.Write([]byte("stuff"))
4531 }
4532 }))
4533 for _, req := range []string{
4534 "GET / HTTP/1.0",
4535 "GET /header HTTP/1.0",
4536 "GET /more HTTP/1.0",
4537 "GET / HTTP/1.1\nHost: foo",
4538 "GET /header HTTP/1.1\nHost: foo",
4539 "GET /more HTTP/1.1\nHost: foo",
4540 } {
4541 got := ht.rawResponse(req)
4542 wantStatus := fmt.Sprintf("%d %s", code, StatusText(code))
4543 if !strings.Contains(got, wantStatus) {
4544 t.Errorf("Code %d: Wanted %q Modified for %q: %s", code, wantStatus, req, got)
4545 } else if strings.Contains(got, "Content-Length") {
4546 t.Errorf("Code %d: Got a Content-Length from %q: %s", code, req, got)
4547 } else if strings.Contains(got, "stuff") {
4548 t.Errorf("Code %d: Response contains a body from %q: %s", code, req, got)
4549 }
4550 }
4551 }
4552 }
4553
4554 func TestContentTypeOkayOn204(t *testing.T) {
4555 ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
4556 w.Header().Set("Content-Length", "123")
4557 w.Header().Set("Content-Type", "foo/bar")
4558 w.WriteHeader(204)
4559 }))
4560 got := ht.rawResponse("GET / HTTP/1.1\nHost: foo")
4561 if !strings.Contains(got, "Content-Type: foo/bar") {
4562 t.Errorf("Response = %q; want Content-Type: foo/bar", got)
4563 }
4564 if strings.Contains(got, "Content-Length: 123") {
4565 t.Errorf("Response = %q; don't want a Content-Length", got)
4566 }
4567 }
4568
4569
4570
4571
4572
4573
4574
4575 func TestTransportAndServerSharedBodyRace(t *testing.T) {
4576 run(t, testTransportAndServerSharedBodyRace, testNotParallel, http3SkippedMode)
4577 }
4578 func testTransportAndServerSharedBodyRace(t *testing.T, mode testMode) {
4579
4580
4581
4582
4583 runTimeSensitiveTest(t, []time.Duration{
4584 1 * time.Millisecond,
4585 5 * time.Millisecond,
4586 10 * time.Millisecond,
4587 50 * time.Millisecond,
4588 100 * time.Millisecond,
4589 500 * time.Millisecond,
4590 time.Second,
4591 5 * time.Second,
4592 }, func(t *testing.T, timeout time.Duration) error {
4593 SetRSTAvoidanceDelay(t, timeout)
4594 t.Logf("set RST avoidance delay to %v", timeout)
4595
4596 const bodySize = 1 << 20
4597
4598 var wg sync.WaitGroup
4599 backend := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
4600
4601
4602
4603
4604
4605
4606
4607
4608 wg.Add(1)
4609 defer wg.Done()
4610
4611 n, err := io.CopyN(rw, req.Body, bodySize)
4612 t.Logf("backend CopyN: %v, %v", n, err)
4613 <-req.Context().Done()
4614 }))
4615
4616
4617 defer func() {
4618 wg.Wait()
4619 backend.close()
4620 }()
4621
4622 var proxy *clientServerTest
4623 proxy = newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
4624 req2, _ := NewRequest("POST", backend.ts.URL, req.Body)
4625 req2.ContentLength = bodySize
4626 cancel := make(chan struct{})
4627 req2.Cancel = cancel
4628
4629 bresp, err := proxy.c.Do(req2)
4630 if err != nil {
4631 t.Errorf("Proxy outbound request: %v", err)
4632 return
4633 }
4634 _, err = io.CopyN(io.Discard, bresp.Body, bodySize/2)
4635 if err != nil {
4636 t.Errorf("Proxy copy error: %v", err)
4637 return
4638 }
4639 t.Cleanup(func() { bresp.Body.Close() })
4640
4641
4642
4643
4644
4645
4646 if mode == http2Mode {
4647 close(cancel)
4648 } else {
4649 proxy.c.Transport.(*Transport).CancelRequest(req2)
4650 }
4651 rw.Write([]byte("OK"))
4652 }))
4653 defer proxy.close()
4654
4655 req, _ := NewRequest("POST", proxy.ts.URL, io.LimitReader(neverEnding('a'), bodySize))
4656 res, err := proxy.c.Do(req)
4657 if err != nil {
4658 return fmt.Errorf("original request: %v", err)
4659 }
4660 res.Body.Close()
4661 return nil
4662 })
4663 }
4664
4665
4666
4667
4668 func TestRequestBodyCloseDoesntBlock(t *testing.T) {
4669 run(t, testRequestBodyCloseDoesntBlock, []testMode{http1Mode})
4670 }
4671 func testRequestBodyCloseDoesntBlock(t *testing.T, mode testMode) {
4672 if testing.Short() {
4673 t.Skip("skipping in -short mode")
4674 }
4675
4676 readErrCh := make(chan error, 1)
4677 errCh := make(chan error, 2)
4678
4679 server := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
4680 go func(body io.Reader) {
4681 _, err := body.Read(make([]byte, 100))
4682 readErrCh <- err
4683 }(req.Body)
4684 time.Sleep(500 * time.Millisecond)
4685 })).ts
4686
4687 closeConn := make(chan bool)
4688 defer close(closeConn)
4689 go func() {
4690 conn, err := net.Dial("tcp", server.Listener.Addr().String())
4691 if err != nil {
4692 errCh <- err
4693 return
4694 }
4695 defer conn.Close()
4696 _, err = conn.Write([]byte("POST / HTTP/1.1\r\nConnection: close\r\nHost: foo\r\nContent-Length: 100000\r\n\r\n"))
4697 if err != nil {
4698 errCh <- err
4699 return
4700 }
4701
4702
4703 <-closeConn
4704 }()
4705 select {
4706 case err := <-readErrCh:
4707 if err == nil {
4708 t.Error("Read was nil. Expected error.")
4709 }
4710 case err := <-errCh:
4711 t.Error(err)
4712 }
4713 }
4714
4715
4716 func TestResponseWriterWriteString(t *testing.T) {
4717 okc := make(chan bool, 1)
4718 ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
4719 _, ok := w.(io.StringWriter)
4720 okc <- ok
4721 }))
4722 ht.rawResponse("GET / HTTP/1.0")
4723 select {
4724 case ok := <-okc:
4725 if !ok {
4726 t.Error("ResponseWriter did not implement io.StringWriter")
4727 }
4728 default:
4729 t.Error("handler was never called")
4730 }
4731 }
4732
4733 func TestServerConnState(t *testing.T) { run(t, testServerConnState, []testMode{http1Mode}) }
4734 func testServerConnState(t *testing.T, mode testMode) {
4735 handler := map[string]func(w ResponseWriter, r *Request){
4736 "/": func(w ResponseWriter, r *Request) {
4737 fmt.Fprintf(w, "Hello.")
4738 },
4739 "/close": func(w ResponseWriter, r *Request) {
4740 w.Header().Set("Connection", "close")
4741 fmt.Fprintf(w, "Hello.")
4742 },
4743 "/hijack": func(w ResponseWriter, r *Request) {
4744 c, _, _ := w.(Hijacker).Hijack()
4745 c.Write([]byte("HTTP/1.0 200 OK\r\nConnection: close\r\n\r\nHello."))
4746 c.Close()
4747 },
4748 "/hijack-panic": func(w ResponseWriter, r *Request) {
4749 c, _, _ := w.(Hijacker).Hijack()
4750 c.Write([]byte("HTTP/1.0 200 OK\r\nConnection: close\r\n\r\nHello."))
4751 c.Close()
4752 panic("intentional panic")
4753 },
4754 }
4755
4756
4757 type stateLog struct {
4758 active net.Conn
4759 got []ConnState
4760 want []ConnState
4761 complete chan<- struct{}
4762 }
4763 activeLog := make(chan *stateLog, 1)
4764
4765
4766
4767
4768 wantLog := func(doRequests func(), want ...ConnState) {
4769 t.Helper()
4770 complete := make(chan struct{})
4771 activeLog <- &stateLog{want: want, complete: complete}
4772
4773 doRequests()
4774
4775 <-complete
4776 sl := <-activeLog
4777 if !slices.Equal(sl.got, sl.want) {
4778 t.Errorf("Request(s) produced unexpected state sequence.\nGot: %v\nWant: %v", sl.got, sl.want)
4779 }
4780
4781
4782
4783 }
4784
4785 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
4786 handler[r.URL.Path](w, r)
4787 }), func(ts *httptest.Server) {
4788 ts.Config.ErrorLog = log.New(io.Discard, "", 0)
4789 ts.Config.ConnState = func(c net.Conn, state ConnState) {
4790 if c == nil {
4791 t.Errorf("nil conn seen in state %s", state)
4792 return
4793 }
4794 sl := <-activeLog
4795 if sl.active == nil && state == StateNew {
4796 sl.active = c
4797 } else if sl.active != c {
4798 t.Errorf("unexpected conn in state %s", state)
4799 activeLog <- sl
4800 return
4801 }
4802 sl.got = append(sl.got, state)
4803 if sl.complete != nil && (len(sl.got) >= len(sl.want) || !slices.Equal(sl.got, sl.want[:len(sl.got)])) {
4804 close(sl.complete)
4805 sl.complete = nil
4806 }
4807 activeLog <- sl
4808 }
4809 }).ts
4810 defer func() {
4811 activeLog <- &stateLog{}
4812 ts.Close()
4813 }()
4814
4815 c := ts.Client()
4816
4817 mustGet := func(url string, headers ...string) {
4818 t.Helper()
4819 req, err := NewRequest("GET", url, nil)
4820 if err != nil {
4821 t.Fatal(err)
4822 }
4823 for len(headers) > 0 {
4824 req.Header.Add(headers[0], headers[1])
4825 headers = headers[2:]
4826 }
4827 res, err := c.Do(req)
4828 if err != nil {
4829 t.Errorf("Error fetching %s: %v", url, err)
4830 return
4831 }
4832 _, err = io.ReadAll(res.Body)
4833 defer res.Body.Close()
4834 if err != nil {
4835 t.Errorf("Error reading %s: %v", url, err)
4836 }
4837 }
4838
4839 wantLog(func() {
4840 mustGet(ts.URL + "/")
4841 mustGet(ts.URL + "/close")
4842 }, StateNew, StateActive, StateIdle, StateActive, StateClosed)
4843
4844 wantLog(func() {
4845 mustGet(ts.URL + "/")
4846 mustGet(ts.URL+"/", "Connection", "close")
4847 }, StateNew, StateActive, StateIdle, StateActive, StateClosed)
4848
4849 wantLog(func() {
4850 mustGet(ts.URL + "/hijack")
4851 }, StateNew, StateActive, StateHijacked)
4852
4853 wantLog(func() {
4854 mustGet(ts.URL + "/hijack-panic")
4855 }, StateNew, StateActive, StateHijacked)
4856
4857 wantLog(func() {
4858 c, err := net.Dial("tcp", ts.Listener.Addr().String())
4859 if err != nil {
4860 t.Fatal(err)
4861 }
4862 c.Close()
4863 }, StateNew, StateClosed)
4864
4865 wantLog(func() {
4866 c, err := net.Dial("tcp", ts.Listener.Addr().String())
4867 if err != nil {
4868 t.Fatal(err)
4869 }
4870 if _, err := io.WriteString(c, "BOGUS REQUEST\r\n\r\n"); err != nil {
4871 t.Fatal(err)
4872 }
4873 c.Read(make([]byte, 1))
4874 c.Close()
4875 }, StateNew, StateActive, StateClosed)
4876
4877 wantLog(func() {
4878 c, err := net.Dial("tcp", ts.Listener.Addr().String())
4879 if err != nil {
4880 t.Fatal(err)
4881 }
4882 if _, err := io.WriteString(c, "GET / HTTP/1.1\r\nHost: foo\r\n\r\n"); err != nil {
4883 t.Fatal(err)
4884 }
4885 res, err := ReadResponse(bufio.NewReader(c), nil)
4886 if err != nil {
4887 t.Fatal(err)
4888 }
4889 if _, err := io.Copy(io.Discard, res.Body); err != nil {
4890 t.Fatal(err)
4891 }
4892 c.Close()
4893 }, StateNew, StateActive, StateIdle, StateClosed)
4894 }
4895
4896 func TestServerKeepAlivesEnabledResultClose(t *testing.T) {
4897 run(t, testServerKeepAlivesEnabledResultClose, []testMode{http1Mode})
4898 }
4899 func testServerKeepAlivesEnabledResultClose(t *testing.T, mode testMode) {
4900 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
4901 }), func(ts *httptest.Server) {
4902 ts.Config.SetKeepAlivesEnabled(false)
4903 }).ts
4904 res, err := ts.Client().Get(ts.URL)
4905 if err != nil {
4906 t.Fatal(err)
4907 }
4908 defer res.Body.Close()
4909 if !res.Close {
4910 t.Errorf("Body.Close == false; want true")
4911 }
4912 }
4913
4914
4915 func TestServerEmptyBodyRace(t *testing.T) { run(t, testServerEmptyBodyRace) }
4916 func testServerEmptyBodyRace(t *testing.T, mode testMode) {
4917 var n int32
4918 cst := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
4919 atomic.AddInt32(&n, 1)
4920 }), optQuietLog)
4921 var wg sync.WaitGroup
4922 const reqs = 20
4923 for i := 0; i < reqs; i++ {
4924 wg.Add(1)
4925 go func() {
4926 defer wg.Done()
4927 res, err := cst.c.Get(cst.ts.URL)
4928 if err != nil {
4929
4930
4931 time.Sleep(10 * time.Millisecond)
4932 res, err = cst.c.Get(cst.ts.URL)
4933 if err != nil {
4934 t.Error(err)
4935 return
4936 }
4937 }
4938 defer res.Body.Close()
4939 _, err = io.Copy(io.Discard, res.Body)
4940 if err != nil {
4941 t.Error(err)
4942 return
4943 }
4944 }()
4945 }
4946 wg.Wait()
4947 if got := atomic.LoadInt32(&n); got != reqs {
4948 t.Errorf("handler ran %d times; want %d", got, reqs)
4949 }
4950 }
4951
4952 func TestServerConnStateNew(t *testing.T) {
4953 sawNew := false
4954 srv := &Server{
4955 ConnState: func(c net.Conn, state ConnState) {
4956 if state == StateNew {
4957 sawNew = true
4958 }
4959 },
4960 Handler: HandlerFunc(func(w ResponseWriter, r *Request) {}),
4961 }
4962 srv.Serve(&oneConnListener{
4963 conn: &rwTestConn{
4964 Reader: strings.NewReader("GET / HTTP/1.1\r\nHost: foo\r\n\r\n"),
4965 Writer: io.Discard,
4966 },
4967 })
4968 if !sawNew {
4969 t.Error("StateNew not seen")
4970 }
4971 }
4972
4973 type closeWriteTestConn struct {
4974 rwTestConn
4975 didCloseWrite bool
4976 }
4977
4978 func (c *closeWriteTestConn) CloseWrite() error {
4979 c.didCloseWrite = true
4980 return nil
4981 }
4982
4983 func TestCloseWrite(t *testing.T) {
4984 SetRSTAvoidanceDelay(t, 1*time.Millisecond)
4985
4986 var srv Server
4987 var testConn closeWriteTestConn
4988 c := ExportServerNewConn(&srv, &testConn)
4989 ExportCloseWriteAndWait(c)
4990 if !testConn.didCloseWrite {
4991 t.Error("didn't see CloseWrite call")
4992 }
4993 }
4994
4995
4996
4997
4998
4999
5000
5001
5002 func TestServerFlushAndHijack(t *testing.T) { run(t, testServerFlushAndHijack, []testMode{http1Mode}) }
5003 func testServerFlushAndHijack(t *testing.T, mode testMode) {
5004 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
5005 io.WriteString(w, "Hello, ")
5006 w.(Flusher).Flush()
5007 conn, buf, _ := w.(Hijacker).Hijack()
5008 buf.WriteString("6\r\nworld!\r\n0\r\n\r\n")
5009 if err := buf.Flush(); err != nil {
5010 t.Error(err)
5011 }
5012 if err := conn.Close(); err != nil {
5013 t.Error(err)
5014 }
5015 })).ts
5016 res, err := Get(ts.URL)
5017 if err != nil {
5018 t.Fatal(err)
5019 }
5020 defer res.Body.Close()
5021 all, err := io.ReadAll(res.Body)
5022 if err != nil {
5023 t.Fatal(err)
5024 }
5025 if want := "Hello, world!"; string(all) != want {
5026 t.Errorf("Got %q; want %q", all, want)
5027 }
5028 }
5029
5030
5031
5032
5033
5034
5035
5036 func TestServerKeepAliveAfterWriteError(t *testing.T) {
5037 run(t, testServerKeepAliveAfterWriteError, []testMode{http1Mode})
5038 }
5039 func testServerKeepAliveAfterWriteError(t *testing.T, mode testMode) {
5040 if testing.Short() {
5041 t.Skip("skipping in -short mode")
5042 }
5043 const numReq = 3
5044 addrc := make(chan string, numReq)
5045 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
5046 addrc <- r.RemoteAddr
5047 time.Sleep(500 * time.Millisecond)
5048 w.(Flusher).Flush()
5049 }), func(ts *httptest.Server) {
5050 ts.Config.WriteTimeout = 250 * time.Millisecond
5051 }).ts
5052
5053 errc := make(chan error, numReq)
5054 go func() {
5055 defer close(errc)
5056 for i := 0; i < numReq; i++ {
5057 res, err := Get(ts.URL)
5058 if res != nil {
5059 res.Body.Close()
5060 }
5061 errc <- err
5062 }
5063 }()
5064
5065 addrSeen := map[string]bool{}
5066 numOkay := 0
5067 for {
5068 select {
5069 case v := <-addrc:
5070 addrSeen[v] = true
5071 case err, ok := <-errc:
5072 if !ok {
5073 if len(addrSeen) != numReq {
5074 t.Errorf("saw %d unique client addresses; want %d", len(addrSeen), numReq)
5075 }
5076 if numOkay != 0 {
5077 t.Errorf("got %d successful client requests; want 0", numOkay)
5078 }
5079 return
5080 }
5081 if err == nil {
5082 numOkay++
5083 }
5084 }
5085 }
5086 }
5087
5088
5089
5090 func TestNoContentLengthIfTransferEncoding(t *testing.T) {
5091 run(t, testNoContentLengthIfTransferEncoding, []testMode{http1Mode})
5092 }
5093 func testNoContentLengthIfTransferEncoding(t *testing.T, mode testMode) {
5094 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
5095 w.Header().Set("Transfer-Encoding", "foo")
5096 io.WriteString(w, "<html>")
5097 })).ts
5098 c, err := net.Dial("tcp", ts.Listener.Addr().String())
5099 if err != nil {
5100 t.Fatalf("Dial: %v", err)
5101 }
5102 defer c.Close()
5103 if _, err := io.WriteString(c, "GET / HTTP/1.1\r\nHost: foo\r\n\r\n"); err != nil {
5104 t.Fatal(err)
5105 }
5106 bs := bufio.NewScanner(c)
5107 var got strings.Builder
5108 for bs.Scan() {
5109 if strings.TrimSpace(bs.Text()) == "" {
5110 break
5111 }
5112 got.WriteString(bs.Text())
5113 got.WriteByte('\n')
5114 }
5115 if err := bs.Err(); err != nil {
5116 t.Fatal(err)
5117 }
5118 if strings.Contains(got.String(), "Content-Length") {
5119 t.Errorf("Unexpected Content-Length in response headers: %s", got.String())
5120 }
5121 if strings.Contains(got.String(), "Content-Type") {
5122 t.Errorf("Unexpected Content-Type in response headers: %s", got.String())
5123 }
5124 }
5125
5126
5127
5128 func TestTolerateCRLFBeforeRequestLine(t *testing.T) {
5129 req := []byte("POST / HTTP/1.1\r\nHost: golang.org\r\nContent-Length: 3\r\n\r\nABC" +
5130 "\r\n\r\n" +
5131 "GET / HTTP/1.1\r\nHost: golang.org\r\n\r\n")
5132 var buf bytes.Buffer
5133 conn := &rwTestConn{
5134 Reader: bytes.NewReader(req),
5135 Writer: &buf,
5136 closec: make(chan bool, 1),
5137 }
5138 ln := &oneConnListener{conn: conn}
5139 numReq := 0
5140 go Serve(ln, HandlerFunc(func(rw ResponseWriter, r *Request) {
5141 numReq++
5142 }))
5143 <-conn.closec
5144 if numReq != 2 {
5145 t.Errorf("num requests = %d; want 2", numReq)
5146 t.Logf("Res: %s", buf.Bytes())
5147 }
5148 }
5149
5150 func TestIssue13893_Expect100(t *testing.T) {
5151
5152 req := reqBytes(`PUT /readbody HTTP/1.1
5153 User-Agent: PycURL/7.22.0
5154 Host: 127.0.0.1:9000
5155 Accept: */*
5156 Expect: 100-continue
5157 Content-Length: 10
5158
5159 HelloWorld
5160
5161 `)
5162 var buf bytes.Buffer
5163 conn := &rwTestConn{
5164 Reader: bytes.NewReader(req),
5165 Writer: &buf,
5166 closec: make(chan bool, 1),
5167 }
5168 ln := &oneConnListener{conn: conn}
5169 go Serve(ln, HandlerFunc(func(w ResponseWriter, r *Request) {
5170 if _, ok := r.Header["Expect"]; !ok {
5171 t.Error("Expect header should not be filtered out")
5172 }
5173 }))
5174 <-conn.closec
5175 }
5176
5177 func TestIssue11549_Expect100(t *testing.T) {
5178 req := reqBytes(`PUT /readbody HTTP/1.1
5179 User-Agent: PycURL/7.22.0
5180 Host: 127.0.0.1:9000
5181 Accept: */*
5182 Expect: 100-continue
5183 Content-Length: 10
5184
5185 HelloWorldPUT /noreadbody HTTP/1.1
5186 User-Agent: PycURL/7.22.0
5187 Host: 127.0.0.1:9000
5188 Accept: */*
5189 Expect: 100-continue
5190 Content-Length: 10
5191
5192 GET /should-be-ignored HTTP/1.1
5193 Host: foo
5194
5195 `)
5196 var buf strings.Builder
5197 conn := &rwTestConn{
5198 Reader: bytes.NewReader(req),
5199 Writer: &buf,
5200 closec: make(chan bool, 1),
5201 }
5202 ln := &oneConnListener{conn: conn}
5203 numReq := 0
5204 go Serve(ln, HandlerFunc(func(w ResponseWriter, r *Request) {
5205 numReq++
5206 if r.URL.Path == "/readbody" {
5207 io.ReadAll(r.Body)
5208 }
5209 io.WriteString(w, "Hello world!")
5210 }))
5211 <-conn.closec
5212 if numReq != 2 {
5213 t.Errorf("num requests = %d; want 2", numReq)
5214 }
5215 if !strings.Contains(buf.String(), "Connection: close\r\n") {
5216 t.Errorf("expected 'Connection: close' in response; got: %s", buf.String())
5217 }
5218 }
5219
5220
5221
5222 func TestHandlerFinishSkipBigContentLengthRead(t *testing.T) {
5223 setParallel(t)
5224 conn := newTestConn()
5225 conn.readBuf.WriteString(
5226 "POST / HTTP/1.1\r\n" +
5227 "Host: test\r\n" +
5228 "Content-Length: 9999999999\r\n" +
5229 "\r\n" + strings.Repeat("a", 1<<20))
5230
5231 ls := &oneConnListener{conn}
5232 var inHandlerLen int
5233 go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
5234 inHandlerLen = conn.readBuf.Len()
5235 rw.WriteHeader(404)
5236 }))
5237 <-conn.closec
5238 afterHandlerLen := conn.readBuf.Len()
5239
5240 if afterHandlerLen != inHandlerLen {
5241 t.Errorf("unexpected implicit read. Read buffer went from %d -> %d", inHandlerLen, afterHandlerLen)
5242 }
5243 }
5244
5245 func TestHandlerSetsBodyNil(t *testing.T) { run(t, testHandlerSetsBodyNil) }
5246 func testHandlerSetsBodyNil(t *testing.T, mode testMode) {
5247 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
5248 r.Body = nil
5249 fmt.Fprintf(w, "%v", r.RemoteAddr)
5250 }))
5251 get := func() string {
5252 res, err := cst.c.Get(cst.ts.URL)
5253 if err != nil {
5254 t.Fatal(err)
5255 }
5256 defer res.Body.Close()
5257 slurp, err := io.ReadAll(res.Body)
5258 if err != nil {
5259 t.Fatal(err)
5260 }
5261 return string(slurp)
5262 }
5263 a, b := get(), get()
5264 if a != b {
5265 t.Errorf("Failed to reuse connections between requests: %v vs %v", a, b)
5266 }
5267 }
5268
5269
5270
5271 func TestServerValidatesHostHeader(t *testing.T) {
5272 tests := []struct {
5273 proto string
5274 host string
5275 want int
5276 }{
5277 {"HTTP/0.9", "", 505},
5278
5279 {"HTTP/1.1", "", 400},
5280 {"HTTP/1.1", "Host: \r\n", 200},
5281 {"HTTP/1.1", "Host: 1.2.3.4\r\n", 200},
5282 {"HTTP/1.1", "Host: foo.com\r\n", 200},
5283 {"HTTP/1.1", "Host: foo-bar_baz.com\r\n", 200},
5284 {"HTTP/1.1", "Host: foo.com:80\r\n", 200},
5285 {"HTTP/1.1", "Host: ::1\r\n", 200},
5286 {"HTTP/1.1", "Host: [::1]\r\n", 200},
5287 {"HTTP/1.1", "Host: [::1]:80\r\n", 200},
5288 {"HTTP/1.1", "Host: [::1%25en0]:80\r\n", 200},
5289 {"HTTP/1.1", "Host: 1.2.3.4\r\n", 200},
5290 {"HTTP/1.1", "Host: \x06\r\n", 400},
5291 {"HTTP/1.1", "Host: \xff\r\n", 400},
5292 {"HTTP/1.1", "Host: {\r\n", 400},
5293 {"HTTP/1.1", "Host: }\r\n", 400},
5294 {"HTTP/1.1", "Host: first\r\nHost: second\r\n", 400},
5295
5296
5297
5298 {"HTTP/1.0", "", 200},
5299 {"HTTP/1.0", "Host: first\r\nHost: second\r\n", 400},
5300 {"HTTP/1.0", "Host: \xff\r\n", 400},
5301
5302
5303 {"PRI * HTTP/2.0", "", 200},
5304
5305
5306 {"CONNECT golang.org:443 HTTP/1.1", "", 200},
5307
5308
5309 {"PRI / HTTP/2.0", "", 505},
5310 {"GET / HTTP/2.0", "", 505},
5311 {"GET / HTTP/3.0", "", 505},
5312 }
5313 for _, tt := range tests {
5314 conn := newTestConn()
5315 methodTarget := "GET / "
5316 if !strings.HasPrefix(tt.proto, "HTTP/") {
5317 methodTarget = ""
5318 }
5319 io.WriteString(&conn.readBuf, methodTarget+tt.proto+"\r\n"+tt.host+"\r\n")
5320
5321 ln := &oneConnListener{conn}
5322 srv := Server{
5323 ErrorLog: quietLog,
5324 Handler: HandlerFunc(func(ResponseWriter, *Request) {}),
5325 }
5326 go srv.Serve(ln)
5327 <-conn.closec
5328 res, err := ReadResponse(bufio.NewReader(&conn.writeBuf), nil)
5329 if err != nil {
5330 t.Errorf("For %s %q, ReadResponse: %v", tt.proto, tt.host, res)
5331 continue
5332 }
5333 if res.StatusCode != tt.want {
5334 t.Errorf("For %s %q, Status = %d; want %d", tt.proto, tt.host, res.StatusCode, tt.want)
5335 }
5336 }
5337 }
5338
5339 func TestServerHandlersCanHandleH2PRI(t *testing.T) {
5340 run(t, testServerHandlersCanHandleH2PRI, []testMode{http1Mode})
5341 }
5342 func testServerHandlersCanHandleH2PRI(t *testing.T, mode testMode) {
5343 const upgradeResponse = "upgrade here"
5344 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
5345 conn, br, err := w.(Hijacker).Hijack()
5346 if err != nil {
5347 t.Error(err)
5348 return
5349 }
5350 defer conn.Close()
5351 if r.Method != "PRI" || r.RequestURI != "*" {
5352 t.Errorf("Got method/target %q %q; want PRI *", r.Method, r.RequestURI)
5353 return
5354 }
5355 if !r.Close {
5356 t.Errorf("Request.Close = true; want false")
5357 }
5358 const want = "SM\r\n\r\n"
5359 buf := make([]byte, len(want))
5360 n, err := io.ReadFull(br, buf)
5361 if err != nil || string(buf[:n]) != want {
5362 t.Errorf("Read = %v, %v (%q), want %q", n, err, buf[:n], want)
5363 return
5364 }
5365 io.WriteString(conn, upgradeResponse)
5366 })).ts
5367
5368 c, err := net.Dial("tcp", ts.Listener.Addr().String())
5369 if err != nil {
5370 t.Fatalf("Dial: %v", err)
5371 }
5372 defer c.Close()
5373 io.WriteString(c, "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n")
5374 slurp, err := io.ReadAll(c)
5375 if err != nil {
5376 t.Fatal(err)
5377 }
5378 if string(slurp) != upgradeResponse {
5379 t.Errorf("Handler response = %q; want %q", slurp, upgradeResponse)
5380 }
5381 }
5382
5383
5384
5385 func TestServerValidatesHeaders(t *testing.T) {
5386 setParallel(t)
5387 tests := []struct {
5388 header string
5389 want int
5390 }{
5391 {"", 200},
5392 {"Foo: bar\r\n", 200},
5393 {"X-Foo: bar\r\n", 200},
5394 {"Foo: a space\r\n", 200},
5395
5396 {"A space: foo\r\n", 400},
5397 {"foo\xffbar: foo\r\n", 400},
5398 {"foo\x00bar: foo\r\n", 400},
5399 {"Foo: " + strings.Repeat("x", 1<<21) + "\r\n", 431},
5400
5401
5402 {"Foo : bar\r\n", 400},
5403 {"Foo\t: bar\r\n", 400},
5404
5405
5406
5407 {": empty key\r\n", 400},
5408
5409
5410
5411
5412 {"Content-Length: notdigits\r\n", 400},
5413 {"Content-Length: notdigits\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\n", 400},
5414
5415 {"foo: foo foo\r\n", 200},
5416 {"foo: foo\tfoo\r\n", 200},
5417 {"foo: foo\x00foo\r\n", 400},
5418 {"foo: foo\x7ffoo\r\n", 400},
5419 {"foo: foo\xfffoo\r\n", 200},
5420 }
5421 for _, tt := range tests {
5422 conn := newTestConn()
5423 io.WriteString(&conn.readBuf, "GET / HTTP/1.1\r\nHost: foo\r\n"+tt.header+"\r\n")
5424
5425 ln := &oneConnListener{conn}
5426 srv := Server{
5427 ErrorLog: quietLog,
5428 Handler: HandlerFunc(func(ResponseWriter, *Request) {}),
5429 }
5430 go srv.Serve(ln)
5431 <-conn.closec
5432 res, err := ReadResponse(bufio.NewReader(&conn.writeBuf), nil)
5433 if err != nil {
5434 t.Errorf("For %q, ReadResponse: %v", tt.header, res)
5435 continue
5436 }
5437 if res.StatusCode != tt.want {
5438 t.Errorf("For %q, Status = %d; want %d", tt.header, res.StatusCode, tt.want)
5439 }
5440 }
5441 }
5442
5443 func TestServerRequestContextCancel_ServeHTTPDone(t *testing.T) {
5444 run(t, testServerRequestContextCancel_ServeHTTPDone, http3SkippedMode)
5445 }
5446 func testServerRequestContextCancel_ServeHTTPDone(t *testing.T, mode testMode) {
5447 ctxc := make(chan context.Context, 1)
5448 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
5449 ctx := r.Context()
5450 select {
5451 case <-ctx.Done():
5452 t.Error("should not be Done in ServeHTTP")
5453 default:
5454 }
5455 ctxc <- ctx
5456 }))
5457 res, err := cst.c.Get(cst.ts.URL)
5458 if err != nil {
5459 t.Fatal(err)
5460 }
5461 res.Body.Close()
5462 ctx := <-ctxc
5463 select {
5464 case <-ctx.Done():
5465 default:
5466 t.Error("context should be done after ServeHTTP completes")
5467 }
5468 }
5469
5470
5471
5472
5473
5474 func TestServerRequestContextCancel_ConnClose(t *testing.T) {
5475 run(t, testServerRequestContextCancel_ConnClose, []testMode{http1Mode})
5476 }
5477 func testServerRequestContextCancel_ConnClose(t *testing.T, mode testMode) {
5478 inHandler := make(chan struct{})
5479 handlerDone := make(chan struct{})
5480 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
5481 close(inHandler)
5482 <-r.Context().Done()
5483 close(handlerDone)
5484 })).ts
5485 c, err := net.Dial("tcp", ts.Listener.Addr().String())
5486 if err != nil {
5487 t.Fatal(err)
5488 }
5489 defer c.Close()
5490 io.WriteString(c, "GET / HTTP/1.1\r\nHost: foo\r\n\r\n")
5491 <-inHandler
5492 c.Close()
5493 <-handlerDone
5494 }
5495
5496 func TestServerContext_ServerContextKey(t *testing.T) {
5497 run(t, testServerContext_ServerContextKey, http3SkippedMode)
5498 }
5499 func testServerContext_ServerContextKey(t *testing.T, mode testMode) {
5500 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
5501 ctx := r.Context()
5502 got := ctx.Value(ServerContextKey)
5503 if _, ok := got.(*Server); !ok {
5504 t.Errorf("context value = %T; want *http.Server", got)
5505 }
5506 }))
5507 res, err := cst.c.Get(cst.ts.URL)
5508 if err != nil {
5509 t.Fatal(err)
5510 }
5511 res.Body.Close()
5512 }
5513
5514 func TestServerContext_LocalAddrContextKey(t *testing.T) {
5515 run(t, testServerContext_LocalAddrContextKey, http3SkippedMode)
5516 }
5517 func testServerContext_LocalAddrContextKey(t *testing.T, mode testMode) {
5518 ch := make(chan any, 1)
5519 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
5520 ch <- r.Context().Value(LocalAddrContextKey)
5521 }))
5522 if _, err := cst.c.Head(cst.ts.URL); err != nil {
5523 t.Fatal(err)
5524 }
5525
5526 host := cst.ts.Listener.Addr().String()
5527 got := <-ch
5528 if addr, ok := got.(net.Addr); !ok {
5529 t.Errorf("local addr value = %T; want net.Addr", got)
5530 } else if fmt.Sprint(addr) != host {
5531 t.Errorf("local addr = %v; want %v", addr, host)
5532 }
5533 }
5534
5535
5536 func TestHandlerSetTransferEncodingChunked(t *testing.T) {
5537 setParallel(t)
5538 defer afterTest(t)
5539 ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
5540 w.Header().Set("Transfer-Encoding", "chunked")
5541 w.Write([]byte("hello"))
5542 }))
5543 resp := ht.rawResponse("GET / HTTP/1.1\nHost: foo")
5544 const hdr = "Transfer-Encoding: chunked"
5545 if n := strings.Count(resp, hdr); n != 1 {
5546 t.Errorf("want 1 occurrence of %q in response, got %v\nresponse: %v", hdr, n, resp)
5547 }
5548 }
5549
5550
5551 func TestHandlerSetTransferEncodingGzip(t *testing.T) {
5552 setParallel(t)
5553 defer afterTest(t)
5554 ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
5555 w.Header().Set("Transfer-Encoding", "gzip")
5556 gz := gzip.NewWriter(w)
5557 gz.Write([]byte("hello"))
5558 gz.Close()
5559 }))
5560 resp := ht.rawResponse("GET / HTTP/1.1\nHost: foo")
5561 for _, v := range []string{"gzip", "chunked"} {
5562 hdr := "Transfer-Encoding: " + v
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 BenchmarkClientServer(b *testing.B) {
5570 run(b, benchmarkClientServer, []testMode{http1Mode, https1Mode, http2Mode})
5571 }
5572 func benchmarkClientServer(b *testing.B, mode testMode) {
5573 b.ReportAllocs()
5574 b.StopTimer()
5575 ts := newClientServerTest(b, mode, HandlerFunc(func(rw ResponseWriter, r *Request) {
5576 fmt.Fprintf(rw, "Hello world.\n")
5577 })).ts
5578 b.StartTimer()
5579
5580 c := ts.Client()
5581 for i := 0; i < b.N; i++ {
5582 res, err := c.Get(ts.URL)
5583 if err != nil {
5584 b.Fatal("Get:", err)
5585 }
5586 all, err := io.ReadAll(res.Body)
5587 res.Body.Close()
5588 if err != nil {
5589 b.Fatal("ReadAll:", err)
5590 }
5591 body := string(all)
5592 if body != "Hello world.\n" {
5593 b.Fatal("Got body:", body)
5594 }
5595 }
5596
5597 b.StopTimer()
5598 }
5599
5600 func BenchmarkClientServerParallel(b *testing.B) {
5601 for _, parallelism := range []int{4, 64} {
5602 b.Run(fmt.Sprint(parallelism), func(b *testing.B) {
5603 run(b, func(b *testing.B, mode testMode) {
5604 benchmarkClientServerParallel(b, parallelism, mode)
5605 }, []testMode{http1Mode, https1Mode, http2Mode})
5606 })
5607 }
5608 }
5609
5610 func benchmarkClientServerParallel(b *testing.B, parallelism int, mode testMode) {
5611 b.ReportAllocs()
5612 ts := newClientServerTest(b, mode, HandlerFunc(func(rw ResponseWriter, r *Request) {
5613 fmt.Fprintf(rw, "Hello world.\n")
5614 })).ts
5615 b.ResetTimer()
5616 b.SetParallelism(parallelism)
5617 b.RunParallel(func(pb *testing.PB) {
5618 c := ts.Client()
5619 for pb.Next() {
5620 res, err := c.Get(ts.URL)
5621 if err != nil {
5622 b.Logf("Get: %v", err)
5623 continue
5624 }
5625 all, err := io.ReadAll(res.Body)
5626 res.Body.Close()
5627 if err != nil {
5628 b.Logf("ReadAll: %v", err)
5629 continue
5630 }
5631 body := string(all)
5632 if body != "Hello world.\n" {
5633 panic("Got body: " + body)
5634 }
5635 }
5636 })
5637 }
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648 func BenchmarkServer(b *testing.B) {
5649 b.ReportAllocs()
5650
5651 if url := os.Getenv("GO_TEST_BENCH_SERVER_URL"); url != "" {
5652 n, err := strconv.Atoi(os.Getenv("GO_TEST_BENCH_CLIENT_N"))
5653 if err != nil {
5654 panic(err)
5655 }
5656 for i := 0; i < n; i++ {
5657 res, err := Get(url)
5658 if err != nil {
5659 log.Panicf("Get: %v", err)
5660 }
5661 all, err := io.ReadAll(res.Body)
5662 res.Body.Close()
5663 if err != nil {
5664 log.Panicf("ReadAll: %v", err)
5665 }
5666 body := string(all)
5667 if body != "Hello world.\n" {
5668 log.Panicf("Got body: %q", body)
5669 }
5670 }
5671 os.Exit(0)
5672 return
5673 }
5674
5675 var res = []byte("Hello world.\n")
5676 b.StopTimer()
5677 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
5678 rw.Header().Set("Content-Type", "text/html; charset=utf-8")
5679 rw.Write(res)
5680 }))
5681 defer ts.Close()
5682 b.StartTimer()
5683
5684 cmd := testenv.Command(b, os.Args[0], "-test.run=^$", "-test.bench=^BenchmarkServer$")
5685 cmd.Env = append([]string{
5686 fmt.Sprintf("GO_TEST_BENCH_CLIENT_N=%d", b.N),
5687 fmt.Sprintf("GO_TEST_BENCH_SERVER_URL=%s", ts.URL),
5688 }, os.Environ()...)
5689 out, err := cmd.CombinedOutput()
5690 if err != nil {
5691 b.Errorf("Test failure: %v, with output: %s", err, out)
5692 }
5693 }
5694
5695
5696 func getNoBody(urlStr string) (*Response, error) {
5697 res, err := Get(urlStr)
5698 if err != nil {
5699 return nil, err
5700 }
5701 res.Body.Close()
5702 return res, nil
5703 }
5704
5705
5706
5707 func BenchmarkClient(b *testing.B) {
5708 var data = []byte("Hello world.\n")
5709
5710 url := startClientBenchmarkServer(b, HandlerFunc(func(w ResponseWriter, _ *Request) {
5711 w.Header().Set("Content-Type", "text/html; charset=utf-8")
5712 w.Write(data)
5713 }))
5714
5715
5716 b.StartTimer()
5717 for i := 0; i < b.N; i++ {
5718 res, err := Get(url)
5719 if err != nil {
5720 b.Fatalf("Get: %v", err)
5721 }
5722 body, err := io.ReadAll(res.Body)
5723 res.Body.Close()
5724 if err != nil {
5725 b.Fatalf("ReadAll: %v", err)
5726 }
5727 if !bytes.Equal(body, data) {
5728 b.Fatalf("Got body: %q", body)
5729 }
5730 }
5731 b.StopTimer()
5732 }
5733
5734 func startClientBenchmarkServer(b *testing.B, handler Handler) string {
5735 b.ReportAllocs()
5736 b.StopTimer()
5737
5738 if server := os.Getenv("GO_TEST_BENCH_SERVER"); server != "" {
5739
5740 port := os.Getenv("GO_TEST_BENCH_SERVER_PORT")
5741 if port == "" {
5742 port = "0"
5743 }
5744 ln, err := net.Listen("tcp", "localhost:"+port)
5745 if err != nil {
5746 log.Fatal(err)
5747 }
5748 fmt.Println(ln.Addr().String())
5749
5750 HandleFunc("/", func(w ResponseWriter, r *Request) {
5751 r.ParseForm()
5752 if r.Form.Get("stop") != "" {
5753 os.Exit(0)
5754 }
5755 handler.ServeHTTP(w, r)
5756 })
5757 var srv Server
5758 log.Fatal(srv.Serve(ln))
5759 }
5760
5761
5762 ctx, cancel := context.WithCancel(context.Background())
5763 cmd := testenv.CommandContext(b, ctx, os.Args[0], "-test.run=^$", "-test.bench=^"+b.Name()+"$")
5764 cmd.Env = append(cmd.Environ(), "GO_TEST_BENCH_SERVER=yes")
5765 cmd.Stderr = os.Stderr
5766 stdout, err := cmd.StdoutPipe()
5767 if err != nil {
5768 b.Fatal(err)
5769 }
5770 if err := cmd.Start(); err != nil {
5771 b.Fatalf("subprocess failed to start: %v", err)
5772 }
5773
5774 done := make(chan error, 1)
5775 go func() {
5776 done <- cmd.Wait()
5777 close(done)
5778 }()
5779
5780
5781
5782 bs := bufio.NewScanner(stdout)
5783 if !bs.Scan() {
5784 b.Fatalf("failed to read listening URL from child: %v", bs.Err())
5785 }
5786 url := "http://" + strings.TrimSpace(bs.Text()) + "/"
5787 if _, err := getNoBody(url); err != nil {
5788 b.Fatalf("initial probe of child process failed: %v", err)
5789 }
5790
5791
5792 b.Cleanup(func() {
5793 getNoBody(url + "?stop=yes")
5794 if err := <-done; err != nil {
5795 b.Fatalf("subprocess failed: %v", err)
5796 }
5797
5798 cancel()
5799 <-done
5800
5801 afterTest(b)
5802 })
5803
5804 return url
5805 }
5806
5807 func BenchmarkClientGzip(b *testing.B) {
5808 const responseSize = 1024 * 1024
5809
5810 var buf bytes.Buffer
5811 gz := gzip.NewWriter(&buf)
5812 if _, err := io.CopyN(gz, crand.Reader, responseSize); err != nil {
5813 b.Fatal(err)
5814 }
5815 gz.Close()
5816
5817 data := buf.Bytes()
5818
5819 url := startClientBenchmarkServer(b, HandlerFunc(func(w ResponseWriter, _ *Request) {
5820 w.Header().Set("Content-Encoding", "gzip")
5821 w.Write(data)
5822 }))
5823
5824
5825 b.StartTimer()
5826 for i := 0; i < b.N; i++ {
5827 res, err := Get(url)
5828 if err != nil {
5829 b.Fatalf("Get: %v", err)
5830 }
5831 n, err := io.Copy(io.Discard, res.Body)
5832 res.Body.Close()
5833 if err != nil {
5834 b.Fatalf("ReadAll: %v", err)
5835 }
5836 if n != responseSize {
5837 b.Fatalf("ReadAll: expected %d bytes, got %d", responseSize, n)
5838 }
5839 }
5840 b.StopTimer()
5841 }
5842
5843 func BenchmarkServerFakeConnNoKeepAlive(b *testing.B) {
5844 b.ReportAllocs()
5845 req := reqBytes(`GET / HTTP/1.0
5846 Host: golang.org
5847 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
5848 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
5849 Accept-Encoding: gzip,deflate,sdch
5850 Accept-Language: en-US,en;q=0.8
5851 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
5852 `)
5853 res := []byte("Hello world!\n")
5854
5855 conn := newTestConn()
5856 handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
5857 rw.Header().Set("Content-Type", "text/html; charset=utf-8")
5858 rw.Write(res)
5859 })
5860 ln := new(oneConnListener)
5861 for i := 0; i < b.N; i++ {
5862 conn.readBuf.Reset()
5863 conn.writeBuf.Reset()
5864 conn.readBuf.Write(req)
5865 ln.conn = conn
5866 Serve(ln, handler)
5867 <-conn.closec
5868 }
5869 }
5870
5871
5872 type repeatReader struct {
5873 content []byte
5874 count int
5875 off int
5876 }
5877
5878 func (r *repeatReader) Read(p []byte) (n int, err error) {
5879 if r.count <= 0 {
5880 return 0, io.EOF
5881 }
5882 n = copy(p, r.content[r.off:])
5883 r.off += n
5884 if r.off == len(r.content) {
5885 r.count--
5886 r.off = 0
5887 }
5888 return
5889 }
5890
5891 func BenchmarkServerFakeConnWithKeepAlive(b *testing.B) {
5892 b.ReportAllocs()
5893
5894 req := reqBytes(`GET / HTTP/1.1
5895 Host: golang.org
5896 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
5897 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
5898 Accept-Encoding: gzip,deflate,sdch
5899 Accept-Language: en-US,en;q=0.8
5900 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
5901 `)
5902 res := []byte("Hello world!\n")
5903
5904 conn := &rwTestConn{
5905 Reader: &repeatReader{content: req, count: b.N},
5906 Writer: io.Discard,
5907 closec: make(chan bool, 1),
5908 }
5909 handled := 0
5910 handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
5911 handled++
5912 rw.Header().Set("Content-Type", "text/html; charset=utf-8")
5913 rw.Write(res)
5914 })
5915 ln := &oneConnListener{conn: conn}
5916 go Serve(ln, handler)
5917 <-conn.closec
5918 if b.N != handled {
5919 b.Errorf("b.N=%d but handled %d", b.N, handled)
5920 }
5921 }
5922
5923
5924
5925 func BenchmarkServerFakeConnWithKeepAliveLite(b *testing.B) {
5926 b.ReportAllocs()
5927
5928 req := reqBytes(`GET / HTTP/1.1
5929 Host: golang.org
5930 `)
5931 res := []byte("Hello world!\n")
5932
5933 conn := &rwTestConn{
5934 Reader: &repeatReader{content: req, count: b.N},
5935 Writer: io.Discard,
5936 closec: make(chan bool, 1),
5937 }
5938 handled := 0
5939 handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
5940 handled++
5941 rw.Write(res)
5942 })
5943 ln := &oneConnListener{conn: conn}
5944 go Serve(ln, handler)
5945 <-conn.closec
5946 if b.N != handled {
5947 b.Errorf("b.N=%d but handled %d", b.N, handled)
5948 }
5949 }
5950
5951 const someResponse = "<html>some response</html>"
5952
5953
5954 var response = bytes.Repeat([]byte(someResponse), 2<<10/len(someResponse))
5955
5956
5957 func BenchmarkServerHandlerTypeLen(b *testing.B) {
5958 benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
5959 w.Header().Set("Content-Type", "text/html")
5960 w.Header().Set("Content-Length", strconv.Itoa(len(response)))
5961 w.Write(response)
5962 }))
5963 }
5964
5965
5966 func BenchmarkServerHandlerNoLen(b *testing.B) {
5967 benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
5968 w.Header().Set("Content-Type", "text/html")
5969 w.Write(response)
5970 }))
5971 }
5972
5973
5974 func BenchmarkServerHandlerNoType(b *testing.B) {
5975 benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
5976 w.Header().Set("Content-Length", strconv.Itoa(len(response)))
5977 w.Write(response)
5978 }))
5979 }
5980
5981
5982 func BenchmarkServerHandlerNoHeader(b *testing.B) {
5983 benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
5984 w.Write(response)
5985 }))
5986 }
5987
5988 func benchmarkHandler(b *testing.B, h Handler) {
5989 b.ReportAllocs()
5990 req := reqBytes(`GET / HTTP/1.1
5991 Host: golang.org
5992 `)
5993 conn := &rwTestConn{
5994 Reader: &repeatReader{content: req, count: b.N},
5995 Writer: io.Discard,
5996 closec: make(chan bool, 1),
5997 }
5998 handled := 0
5999 handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
6000 handled++
6001 h.ServeHTTP(rw, r)
6002 })
6003 ln := &oneConnListener{conn: conn}
6004 go Serve(ln, handler)
6005 <-conn.closec
6006 if b.N != handled {
6007 b.Errorf("b.N=%d but handled %d", b.N, handled)
6008 }
6009 }
6010
6011 func BenchmarkServerHijack(b *testing.B) {
6012 b.ReportAllocs()
6013 req := reqBytes(`GET / HTTP/1.1
6014 Host: golang.org
6015 `)
6016 h := HandlerFunc(func(w ResponseWriter, r *Request) {
6017 conn, _, err := w.(Hijacker).Hijack()
6018 if err != nil {
6019 panic(err)
6020 }
6021 conn.Close()
6022 })
6023 conn := &rwTestConn{
6024 Writer: io.Discard,
6025 closec: make(chan bool, 1),
6026 }
6027 ln := &oneConnListener{conn: conn}
6028 for i := 0; i < b.N; i++ {
6029 conn.Reader = bytes.NewReader(req)
6030 ln.conn = conn
6031 Serve(ln, h)
6032 <-conn.closec
6033 }
6034 }
6035
6036 func BenchmarkCloseNotifier(b *testing.B) { run(b, benchmarkCloseNotifier, []testMode{http1Mode}) }
6037 func benchmarkCloseNotifier(b *testing.B, mode testMode) {
6038 b.ReportAllocs()
6039 b.StopTimer()
6040 sawClose := make(chan bool)
6041 ts := newClientServerTest(b, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
6042 <-rw.(CloseNotifier).CloseNotify()
6043 sawClose <- true
6044 })).ts
6045 b.StartTimer()
6046 for i := 0; i < b.N; i++ {
6047 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
6048 if err != nil {
6049 b.Fatalf("error dialing: %v", err)
6050 }
6051 _, err = fmt.Fprintf(conn, "GET / HTTP/1.1\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n")
6052 if err != nil {
6053 b.Fatal(err)
6054 }
6055 conn.Close()
6056 <-sawClose
6057 }
6058 b.StopTimer()
6059 }
6060
6061
6062 func TestConcurrentServerServe(t *testing.T) {
6063 setParallel(t)
6064 for i := 0; i < 100; i++ {
6065 ln1 := &oneConnListener{conn: nil}
6066 ln2 := &oneConnListener{conn: nil}
6067 srv := Server{}
6068 go func() { srv.Serve(ln1) }()
6069 go func() { srv.Serve(ln2) }()
6070 }
6071 }
6072
6073 func TestServerIdleTimeout(t *testing.T) { run(t, testServerIdleTimeout, []testMode{http1Mode}) }
6074 func testServerIdleTimeout(t *testing.T, mode testMode) {
6075 if testing.Short() {
6076 t.Skip("skipping in short mode")
6077 }
6078 runTimeSensitiveTest(t, []time.Duration{
6079 10 * time.Millisecond,
6080 100 * time.Millisecond,
6081 1 * time.Second,
6082 10 * time.Second,
6083 }, func(t *testing.T, readHeaderTimeout time.Duration) error {
6084 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
6085 io.Copy(io.Discard, r.Body)
6086 io.WriteString(w, r.RemoteAddr)
6087 }), func(ts *httptest.Server) {
6088 ts.Config.ReadHeaderTimeout = readHeaderTimeout
6089 ts.Config.IdleTimeout = 2 * readHeaderTimeout
6090 })
6091 defer cst.close()
6092 ts := cst.ts
6093 t.Logf("ReadHeaderTimeout = %v", ts.Config.ReadHeaderTimeout)
6094 t.Logf("IdleTimeout = %v", ts.Config.IdleTimeout)
6095 c := ts.Client()
6096
6097 get := func() (string, error) {
6098 res, err := c.Get(ts.URL)
6099 if err != nil {
6100 return "", err
6101 }
6102 defer res.Body.Close()
6103 slurp, err := io.ReadAll(res.Body)
6104 if err != nil {
6105
6106
6107
6108 t.Fatal(err)
6109 }
6110 return string(slurp), nil
6111 }
6112
6113 a1, err := get()
6114 if err != nil {
6115 return err
6116 }
6117 a2, err := get()
6118 if err != nil {
6119 return err
6120 }
6121 if a1 != a2 {
6122 return fmt.Errorf("did requests on different connections")
6123 }
6124 time.Sleep(ts.Config.IdleTimeout * 3 / 2)
6125 a3, err := get()
6126 if err != nil {
6127 return err
6128 }
6129 if a2 == a3 {
6130 return fmt.Errorf("request three unexpectedly on same connection")
6131 }
6132
6133
6134 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
6135 if err != nil {
6136 return err
6137 }
6138 defer conn.Close()
6139 conn.Write([]byte("GET / HTTP/1.1\r\nHost: foo.com\r\n"))
6140 time.Sleep(ts.Config.ReadHeaderTimeout * 2)
6141 if _, err := io.CopyN(io.Discard, conn, 1); err == nil {
6142 return fmt.Errorf("copy byte succeeded; want err")
6143 }
6144
6145 return nil
6146 })
6147 }
6148
6149 func get(t *testing.T, c *Client, url string) string {
6150 res, err := c.Get(url)
6151 if err != nil {
6152 t.Fatal(err)
6153 }
6154 defer res.Body.Close()
6155 slurp, err := io.ReadAll(res.Body)
6156 if err != nil {
6157 t.Fatal(err)
6158 }
6159 return string(slurp)
6160 }
6161
6162
6163
6164 func TestServerSetKeepAlivesEnabledClosesConns(t *testing.T) {
6165 run(t, testServerSetKeepAlivesEnabledClosesConns, []testMode{http1Mode})
6166 }
6167 func testServerSetKeepAlivesEnabledClosesConns(t *testing.T, mode testMode) {
6168 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
6169 io.WriteString(w, r.RemoteAddr)
6170 })).ts
6171
6172 c := ts.Client()
6173 tr := c.Transport.(*Transport)
6174
6175 get := func() string { return get(t, c, ts.URL) }
6176
6177 a1, a2 := get(), get()
6178 if a1 == a2 {
6179 t.Logf("made two requests from a single conn %q (as expected)", a1)
6180 } else {
6181 t.Errorf("server reported requests from %q and %q; expected same connection", a1, a2)
6182 }
6183
6184
6185
6186
6187
6188 if conns := tr.IdleConnStrsForTesting(); len(conns) != 1 {
6189 t.Errorf("found %d idle conns (%q); want 1", len(conns), conns)
6190 }
6191
6192
6193 ts.Config.SetKeepAlivesEnabled(false)
6194
6195 waitCondition(t, 10*time.Millisecond, func(d time.Duration) bool {
6196 if conns := tr.IdleConnStrsForTesting(); len(conns) > 0 {
6197 if d > 0 {
6198 t.Logf("idle conns %v after SetKeepAlivesEnabled called = %q; waiting for empty", d, conns)
6199 }
6200 return false
6201 }
6202 return true
6203 })
6204
6205
6206
6207
6208 }
6209
6210 func TestServerShutdown(t *testing.T) { run(t, testServerShutdown, http3SkippedMode) }
6211 func testServerShutdown(t *testing.T, mode testMode) {
6212 var cst *clientServerTest
6213
6214 var once sync.Once
6215 statesRes := make(chan map[ConnState]int, 1)
6216 shutdownRes := make(chan error, 1)
6217 gotOnShutdown := make(chan struct{})
6218 handler := HandlerFunc(func(w ResponseWriter, r *Request) {
6219 first := false
6220 once.Do(func() {
6221 statesRes <- cst.ts.Config.ExportAllConnsByState()
6222 go func() {
6223 shutdownRes <- cst.ts.Config.Shutdown(context.Background())
6224 }()
6225 first = true
6226 })
6227
6228 if first {
6229
6230
6231
6232 <-gotOnShutdown
6233
6234
6235 for !t.Failed() {
6236 res, err := cst.c.Get(cst.ts.URL)
6237 if err != nil {
6238 break
6239 }
6240 out, _ := io.ReadAll(res.Body)
6241 res.Body.Close()
6242 if mode == http2Mode {
6243 t.Logf("%v: unexpected success (%q). Listener should be closed before OnShutdown is called.", cst.ts.URL, out)
6244 t.Logf("Retrying to work around https://go.dev/issue/59038.")
6245 continue
6246 }
6247 t.Errorf("%v: unexpected success (%q). Listener should be closed before OnShutdown is called.", cst.ts.URL, out)
6248 }
6249 }
6250
6251 io.WriteString(w, r.RemoteAddr)
6252 })
6253
6254 cst = newClientServerTest(t, mode, handler, func(srv *httptest.Server) {
6255 srv.Config.RegisterOnShutdown(func() { close(gotOnShutdown) })
6256 })
6257
6258 out := get(t, cst.c, cst.ts.URL)
6259 t.Logf("%v: %q", cst.ts.URL, out)
6260
6261 if err := <-shutdownRes; err != nil {
6262 t.Fatalf("Shutdown: %v", err)
6263 }
6264 <-gotOnShutdown
6265
6266 if states := <-statesRes; states[StateActive] != 1 {
6267 t.Errorf("connection in wrong state, %v", states)
6268 }
6269 }
6270
6271 func TestServerShutdownStateNew(t *testing.T) {
6272 runSynctest(t, testServerShutdownStateNew, http3SkippedMode)
6273 }
6274 func testServerShutdownStateNew(t *testing.T, mode testMode) {
6275 if testing.Short() {
6276 t.Skip("test takes 5-6 seconds; skipping in short mode")
6277 }
6278
6279 listener := fakeNetListen()
6280 defer listener.Close()
6281
6282 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
6283
6284 }), func(ts *httptest.Server) {
6285 ts.Listener.Close()
6286 ts.Listener = listener
6287
6288 ts.Config.ErrorLog = log.New(io.Discard, "", 0)
6289 }).ts
6290
6291
6292 c := listener.connect()
6293 defer c.Close()
6294 synctest.Wait()
6295
6296 shutdownRes := runAsync(func() (struct{}, error) {
6297 return struct{}{}, ts.Config.Shutdown(context.Background())
6298 })
6299
6300
6301
6302
6303 const expectTimeout = 5 * time.Second
6304
6305
6306 time.Sleep(expectTimeout - 1)
6307 synctest.Wait()
6308 if shutdownRes.done() {
6309 t.Fatal("shutdown too soon")
6310 }
6311 if c.IsClosedByPeer() {
6312 t.Fatal("connection was closed by server too soon")
6313 }
6314
6315
6316
6317
6318
6319 time.Sleep(2 * time.Second)
6320 synctest.Wait()
6321 if _, err := shutdownRes.result(); err != nil {
6322 t.Fatalf("Shutdown() = %v, want complete", err)
6323 }
6324 if !c.IsClosedByPeer() {
6325 t.Fatalf("connection was not closed by server after shutdown")
6326 }
6327 }
6328
6329
6330 func TestServerCloseDeadlock(t *testing.T) {
6331 var s Server
6332 s.Close()
6333 s.Close()
6334 }
6335
6336
6337
6338 func TestServerKeepAlivesEnabled(t *testing.T) {
6339 runSynctest(t, testServerKeepAlivesEnabled, http3SkippedMode)
6340 }
6341 func testServerKeepAlivesEnabled(t *testing.T, mode testMode) {
6342 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {}), optFakeNet)
6343 defer cst.close()
6344 srv := cst.ts.Config
6345 srv.SetKeepAlivesEnabled(false)
6346 for try := range 2 {
6347 synctest.Wait()
6348 if !srv.ExportAllConnsIdle() {
6349 t.Fatalf("test server still has active conns before request %v", try)
6350 }
6351 conns := 0
6352 var info httptrace.GotConnInfo
6353 ctx := httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{
6354 GotConn: func(v httptrace.GotConnInfo) {
6355 conns++
6356 info = v
6357 },
6358 })
6359 req, err := NewRequestWithContext(ctx, "GET", cst.ts.URL, nil)
6360 if err != nil {
6361 t.Fatal(err)
6362 }
6363 res, err := cst.c.Do(req)
6364 if err != nil {
6365 t.Fatal(err)
6366 }
6367 res.Body.Close()
6368 if conns != 1 {
6369 t.Fatalf("request %v: got %v conns, want 1", try, conns)
6370 }
6371 if info.Reused || info.WasIdle {
6372 t.Fatalf("request %v: Reused=%v (want false), WasIdle=%v (want false)", try, info.Reused, info.WasIdle)
6373 }
6374 }
6375 }
6376
6377
6378
6379
6380 func TestServerCancelsReadTimeoutWhenIdle(t *testing.T) { run(t, testServerCancelsReadTimeoutWhenIdle) }
6381 func testServerCancelsReadTimeoutWhenIdle(t *testing.T, mode testMode) {
6382 runTimeSensitiveTest(t, []time.Duration{
6383 10 * time.Millisecond,
6384 50 * time.Millisecond,
6385 250 * time.Millisecond,
6386 time.Second,
6387 2 * time.Second,
6388 }, func(t *testing.T, timeout time.Duration) error {
6389 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
6390 select {
6391 case <-time.After(2 * timeout):
6392 fmt.Fprint(w, "ok")
6393 case <-r.Context().Done():
6394 fmt.Fprint(w, r.Context().Err())
6395 }
6396 }), func(ts *httptest.Server) {
6397 ts.Config.ReadTimeout = timeout
6398 t.Logf("Server.Config.ReadTimeout = %v", timeout)
6399 })
6400 defer cst.close()
6401 ts := cst.ts
6402
6403 var retries atomic.Int32
6404 cst.c.Transport.(*Transport).Proxy = func(*Request) (*url.URL, error) {
6405 if retries.Add(1) != 1 {
6406 return nil, errors.New("too many retries")
6407 }
6408 return nil, nil
6409 }
6410
6411 c := ts.Client()
6412
6413 res, err := c.Get(ts.URL)
6414 if err != nil {
6415 return fmt.Errorf("Get: %v", err)
6416 }
6417 slurp, err := io.ReadAll(res.Body)
6418 res.Body.Close()
6419 if err != nil {
6420 return fmt.Errorf("Body ReadAll: %v", err)
6421 }
6422 if string(slurp) != "ok" {
6423 return fmt.Errorf("got: %q, want ok", slurp)
6424 }
6425 return nil
6426 })
6427 }
6428
6429
6430
6431
6432 func TestServerCancelsReadHeaderTimeoutWhenIdle(t *testing.T) {
6433 run(t, testServerCancelsReadHeaderTimeoutWhenIdle, []testMode{http1Mode})
6434 }
6435 func testServerCancelsReadHeaderTimeoutWhenIdle(t *testing.T, mode testMode) {
6436 runTimeSensitiveTest(t, []time.Duration{
6437 10 * time.Millisecond,
6438 50 * time.Millisecond,
6439 250 * time.Millisecond,
6440 time.Second,
6441 2 * time.Second,
6442 }, func(t *testing.T, timeout time.Duration) error {
6443 cst := newClientServerTest(t, mode, serve(200), func(ts *httptest.Server) {
6444 ts.Config.ReadHeaderTimeout = timeout
6445 ts.Config.IdleTimeout = 0
6446 })
6447 defer cst.close()
6448 ts := cst.ts
6449
6450
6451
6452 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
6453 if err != nil {
6454 t.Fatalf("dial failed: %v", err)
6455 }
6456 br := bufio.NewReader(conn)
6457 defer conn.Close()
6458
6459 if _, err := conn.Write([]byte("GET / HTTP/1.1\r\nHost: e.com\r\n\r\n")); err != nil {
6460 return fmt.Errorf("writing first request failed: %v", err)
6461 }
6462
6463 if _, err := ReadResponse(br, nil); err != nil {
6464 return fmt.Errorf("first response (before timeout) failed: %v", err)
6465 }
6466
6467
6468
6469 time.Sleep(timeout * 3 / 2)
6470
6471 if _, err := conn.Write([]byte("GET / HTTP/1.1\r\nHost: e.com\r\n\r\n")); err != nil {
6472 return fmt.Errorf("writing second request failed: %v", err)
6473 }
6474
6475 if _, err := ReadResponse(br, nil); err != nil {
6476 return fmt.Errorf("second response (after timeout) failed: %v", err)
6477 }
6478
6479 return nil
6480 })
6481 }
6482
6483
6484
6485 func runTimeSensitiveTest(t *testing.T, durations []time.Duration, test func(t *testing.T, d time.Duration) error) {
6486 for i, d := range durations {
6487 err := test(t, d)
6488 if err == nil {
6489 return
6490 }
6491 if i == len(durations)-1 || t.Failed() {
6492 t.Fatalf("failed with duration %v: %v", d, err)
6493 }
6494 t.Logf("retrying after error with duration %v: %v", d, err)
6495 }
6496 }
6497
6498
6499
6500 func TestServerDuplicateBackgroundRead(t *testing.T) {
6501 run(t, testServerDuplicateBackgroundRead, []testMode{http1Mode})
6502 }
6503 func testServerDuplicateBackgroundRead(t *testing.T, mode testMode) {
6504 if runtime.GOOS == "netbsd" && runtime.GOARCH == "arm" {
6505 testenv.SkipFlaky(t, 24826)
6506 }
6507
6508 goroutines := 5
6509 requests := 2000
6510 if testing.Short() {
6511 goroutines = 3
6512 requests = 100
6513 }
6514
6515 hts := newClientServerTest(t, mode, HandlerFunc(NotFound)).ts
6516
6517 reqBytes := []byte("GET / HTTP/1.1\r\nHost: e.com\r\n\r\n")
6518
6519 var wg sync.WaitGroup
6520 for i := 0; i < goroutines; i++ {
6521 wg.Add(1)
6522 go func() {
6523 defer wg.Done()
6524 cn, err := net.Dial("tcp", hts.Listener.Addr().String())
6525 if err != nil {
6526 t.Error(err)
6527 return
6528 }
6529 defer cn.Close()
6530
6531 wg.Add(1)
6532 go func() {
6533 defer wg.Done()
6534 io.Copy(io.Discard, cn)
6535 }()
6536
6537 for j := 0; j < requests; j++ {
6538 if t.Failed() {
6539 return
6540 }
6541 _, err := cn.Write(reqBytes)
6542 if err != nil {
6543 t.Error(err)
6544 return
6545 }
6546 }
6547 }()
6548 }
6549 wg.Wait()
6550 }
6551
6552
6553
6554
6555
6556
6557 func TestServerHijackGetsBackgroundByte(t *testing.T) {
6558 run(t, testServerHijackGetsBackgroundByte, []testMode{http1Mode})
6559 }
6560 func testServerHijackGetsBackgroundByte(t *testing.T, mode testMode) {
6561 if runtime.GOOS == "plan9" {
6562 t.Skip("skipping test; see https://golang.org/issue/18657")
6563 }
6564 done := make(chan struct{})
6565 inHandler := make(chan bool, 1)
6566 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
6567 defer close(done)
6568
6569
6570 inHandler <- true
6571
6572 conn, buf, err := w.(Hijacker).Hijack()
6573 if err != nil {
6574 t.Error(err)
6575 return
6576 }
6577 defer conn.Close()
6578
6579 peek, err := buf.Reader.Peek(3)
6580 if string(peek) != "foo" || err != nil {
6581 t.Errorf("Peek = %q, %v; want foo, nil", peek, err)
6582 }
6583
6584 select {
6585 case <-r.Context().Done():
6586 t.Error("context unexpectedly canceled")
6587 default:
6588 }
6589 })).ts
6590
6591 cn, err := net.Dial("tcp", ts.Listener.Addr().String())
6592 if err != nil {
6593 t.Fatal(err)
6594 }
6595 defer cn.Close()
6596 if _, err := cn.Write([]byte("GET / HTTP/1.1\r\nHost: e.com\r\n\r\n")); err != nil {
6597 t.Fatal(err)
6598 }
6599 <-inHandler
6600 if _, err := cn.Write([]byte("foo")); err != nil {
6601 t.Fatal(err)
6602 }
6603
6604 if err := cn.(*net.TCPConn).CloseWrite(); err != nil {
6605 t.Fatal(err)
6606 }
6607 <-done
6608 }
6609
6610
6611 func TestServerHijackGetsFullBody(t *testing.T) {
6612 run(t, testServerHijackGetsFullBody, []testMode{http1Mode})
6613 }
6614 func testServerHijackGetsFullBody(t *testing.T, mode testMode) {
6615 if runtime.GOOS == "plan9" {
6616 t.Skip("skipping test; see https://golang.org/issue/18657")
6617 }
6618 done := make(chan struct{})
6619 needle := strings.Repeat("x", 100*1024)
6620 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
6621 defer close(done)
6622
6623 conn, buf, err := w.(Hijacker).Hijack()
6624 if err != nil {
6625 t.Error(err)
6626 return
6627 }
6628 defer conn.Close()
6629
6630 got := make([]byte, len(needle))
6631 n, err := io.ReadFull(buf.Reader, got)
6632 if n != len(needle) || string(got) != needle || err != nil {
6633 t.Errorf("Peek = %q, %v; want 'x'*4096, nil", got, err)
6634 }
6635 })).ts
6636
6637 cn, err := net.Dial("tcp", ts.Listener.Addr().String())
6638 if err != nil {
6639 t.Fatal(err)
6640 }
6641 defer cn.Close()
6642 buf := []byte("GET / HTTP/1.1\r\nHost: e.com\r\n\r\n")
6643 buf = append(buf, []byte(needle)...)
6644 if _, err := cn.Write(buf); err != nil {
6645 t.Fatal(err)
6646 }
6647
6648 if err := cn.(*net.TCPConn).CloseWrite(); err != nil {
6649 t.Fatal(err)
6650 }
6651 <-done
6652 }
6653
6654
6655
6656
6657 func TestServerHijackGetsBackgroundByte_big(t *testing.T) {
6658 run(t, testServerHijackGetsBackgroundByte_big, []testMode{http1Mode})
6659 }
6660 func testServerHijackGetsBackgroundByte_big(t *testing.T, mode testMode) {
6661 if runtime.GOOS == "plan9" {
6662 t.Skip("skipping test; see https://golang.org/issue/18657")
6663 }
6664 done := make(chan struct{})
6665 const size = 8 << 10
6666 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
6667 defer close(done)
6668
6669 conn, buf, err := w.(Hijacker).Hijack()
6670 if err != nil {
6671 t.Error(err)
6672 return
6673 }
6674 defer conn.Close()
6675 slurp, err := io.ReadAll(buf.Reader)
6676 if err != nil {
6677 t.Errorf("Copy: %v", err)
6678 }
6679 allX := true
6680 for _, v := range slurp {
6681 if v != 'x' {
6682 allX = false
6683 }
6684 }
6685 if len(slurp) != size {
6686 t.Errorf("read %d; want %d", len(slurp), size)
6687 } else if !allX {
6688 t.Errorf("read %q; want %d 'x'", slurp, size)
6689 }
6690 })).ts
6691
6692 cn, err := net.Dial("tcp", ts.Listener.Addr().String())
6693 if err != nil {
6694 t.Fatal(err)
6695 }
6696 defer cn.Close()
6697 if _, err := fmt.Fprintf(cn, "GET / HTTP/1.1\r\nHost: e.com\r\n\r\n%s",
6698 strings.Repeat("x", size)); err != nil {
6699 t.Fatal(err)
6700 }
6701 if err := cn.(*net.TCPConn).CloseWrite(); err != nil {
6702 t.Fatal(err)
6703 }
6704
6705 <-done
6706 }
6707
6708
6709 func TestServerValidatesMethod(t *testing.T) {
6710 tests := []struct {
6711 method string
6712 want int
6713 }{
6714 {"GET", 200},
6715 {"GE(T", 400},
6716 }
6717 for _, tt := range tests {
6718 conn := newTestConn()
6719 io.WriteString(&conn.readBuf, tt.method+" / HTTP/1.1\r\nHost: foo.example\r\n\r\n")
6720
6721 ln := &oneConnListener{conn}
6722 go Serve(ln, serve(200))
6723 <-conn.closec
6724 res, err := ReadResponse(bufio.NewReader(&conn.writeBuf), nil)
6725 if err != nil {
6726 t.Errorf("For %s, ReadResponse: %v", tt.method, res)
6727 continue
6728 }
6729 if res.StatusCode != tt.want {
6730 t.Errorf("For %s, Status = %d; want %d", tt.method, res.StatusCode, tt.want)
6731 }
6732 }
6733 }
6734
6735
6736 type eofListenerNotComparable []int
6737
6738 func (eofListenerNotComparable) Accept() (net.Conn, error) { return nil, io.EOF }
6739 func (eofListenerNotComparable) Addr() net.Addr { return nil }
6740 func (eofListenerNotComparable) Close() error { return nil }
6741
6742
6743 func TestServerListenNotComparableListener(t *testing.T) {
6744 var s Server
6745 s.Serve(make(eofListenerNotComparable, 1))
6746 }
6747
6748
6749 type countCloseListener struct {
6750 net.Listener
6751 closes int32
6752 }
6753
6754 func (p *countCloseListener) Close() error {
6755 var err error
6756 if n := atomic.AddInt32(&p.closes, 1); n == 1 && p.Listener != nil {
6757 err = p.Listener.Close()
6758 }
6759 return err
6760 }
6761
6762
6763 func TestServerCloseListenerOnce(t *testing.T) {
6764 setParallel(t)
6765 defer afterTest(t)
6766
6767 ln := newLocalListener(t)
6768 defer ln.Close()
6769
6770 cl := &countCloseListener{Listener: ln}
6771 server := &Server{}
6772 sdone := make(chan bool, 1)
6773
6774 go func() {
6775 server.Serve(cl)
6776 sdone <- true
6777 }()
6778 time.Sleep(10 * time.Millisecond)
6779 server.Shutdown(context.Background())
6780 ln.Close()
6781 <-sdone
6782
6783 nclose := atomic.LoadInt32(&cl.closes)
6784 if nclose != 1 {
6785 t.Errorf("Close calls = %v; want 1", nclose)
6786 }
6787 }
6788
6789
6790 func TestServerShutdownThenServe(t *testing.T) {
6791 var srv Server
6792 cl := &countCloseListener{Listener: nil}
6793 srv.Shutdown(context.Background())
6794 got := srv.Serve(cl)
6795 if got != ErrServerClosed {
6796 t.Errorf("Serve err = %v; want ErrServerClosed", got)
6797 }
6798 nclose := atomic.LoadInt32(&cl.closes)
6799 if nclose != 1 {
6800 t.Errorf("Close calls = %v; want 1", nclose)
6801 }
6802 }
6803
6804
6805 func TestStripPortFromHost(t *testing.T) {
6806 mux := NewServeMux()
6807
6808 mux.HandleFunc("example.com/", func(w ResponseWriter, r *Request) {
6809 fmt.Fprintf(w, "OK")
6810 })
6811 mux.HandleFunc("example.com:9000/", func(w ResponseWriter, r *Request) {
6812 fmt.Fprintf(w, "uh-oh!")
6813 })
6814
6815 req := httptest.NewRequest("GET", "http://example.com:9000/", nil)
6816 rw := httptest.NewRecorder()
6817
6818 mux.ServeHTTP(rw, req)
6819
6820 response := rw.Body.String()
6821 if response != "OK" {
6822 t.Errorf("Response gotten was %q", response)
6823 }
6824 }
6825
6826 func TestServerContexts(t *testing.T) { run(t, testServerContexts, http3SkippedMode) }
6827 func testServerContexts(t *testing.T, mode testMode) {
6828 type baseKey struct{}
6829 type connKey struct{}
6830 ch := make(chan context.Context, 1)
6831 ts := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, r *Request) {
6832 ch <- r.Context()
6833 }), func(ts *httptest.Server) {
6834 ts.Config.BaseContext = func(ln net.Listener) context.Context {
6835 if strings.Contains(reflect.TypeOf(ln).String(), "onceClose") {
6836 t.Errorf("unexpected onceClose listener type %T", ln)
6837 }
6838 return context.WithValue(context.Background(), baseKey{}, "base")
6839 }
6840 ts.Config.ConnContext = func(ctx context.Context, c net.Conn) context.Context {
6841 if got, want := ctx.Value(baseKey{}), "base"; got != want {
6842 t.Errorf("in ConnContext, base context key = %#v; want %q", got, want)
6843 }
6844 return context.WithValue(ctx, connKey{}, "conn")
6845 }
6846 }).ts
6847 res, err := ts.Client().Get(ts.URL)
6848 if err != nil {
6849 t.Fatal(err)
6850 }
6851 res.Body.Close()
6852 ctx := <-ch
6853 if got, want := ctx.Value(baseKey{}), "base"; got != want {
6854 t.Errorf("base context key = %#v; want %q", got, want)
6855 }
6856 if got, want := ctx.Value(connKey{}), "conn"; got != want {
6857 t.Errorf("conn context key = %#v; want %q", got, want)
6858 }
6859 }
6860
6861
6862 func TestConnContextNotModifyingAllContexts(t *testing.T) {
6863 run(t, testConnContextNotModifyingAllContexts)
6864 }
6865 func testConnContextNotModifyingAllContexts(t *testing.T, mode testMode) {
6866 type connKey struct{}
6867 ts := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, r *Request) {
6868 rw.Header().Set("Connection", "close")
6869 }), func(ts *httptest.Server) {
6870 ts.Config.ConnContext = func(ctx context.Context, c net.Conn) context.Context {
6871 if got := ctx.Value(connKey{}); got != nil {
6872 t.Errorf("in ConnContext, unexpected context key = %#v", got)
6873 }
6874 return context.WithValue(ctx, connKey{}, "conn")
6875 }
6876 }).ts
6877
6878 var res *Response
6879 var err error
6880
6881 res, err = ts.Client().Get(ts.URL)
6882 if err != nil {
6883 t.Fatal(err)
6884 }
6885 res.Body.Close()
6886
6887 res, err = ts.Client().Get(ts.URL)
6888 if err != nil {
6889 t.Fatal(err)
6890 }
6891 res.Body.Close()
6892 }
6893
6894
6895
6896 func TestUnsupportedTransferEncodingsReturn501(t *testing.T) {
6897 run(t, testUnsupportedTransferEncodingsReturn501, []testMode{http1Mode})
6898 }
6899 func testUnsupportedTransferEncodingsReturn501(t *testing.T, mode testMode) {
6900 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
6901 w.Write([]byte("Hello, World!"))
6902 })).ts
6903
6904 serverURL, err := url.Parse(cst.URL)
6905 if err != nil {
6906 t.Fatalf("Failed to parse server URL: %v", err)
6907 }
6908
6909 unsupportedTEs := []string{
6910 "fugazi",
6911 "foo-bar",
6912 "unknown",
6913 `" chunked"`,
6914 }
6915
6916 for _, badTE := range unsupportedTEs {
6917 http1ReqBody := fmt.Sprintf(""+
6918 "POST / HTTP/1.1\r\nConnection: close\r\n"+
6919 "Host: localhost\r\nTransfer-Encoding: %s\r\n\r\n", badTE)
6920
6921 gotBody, err := fetchWireResponse(serverURL.Host, []byte(http1ReqBody))
6922 if err != nil {
6923 t.Errorf("%q. unexpected error: %v", badTE, err)
6924 continue
6925 }
6926
6927 wantBody := fmt.Sprintf("" +
6928 "HTTP/1.1 501 Not Implemented\r\nContent-Type: text/plain; charset=utf-8\r\n" +
6929 "Connection: close\r\n\r\nUnsupported transfer encoding")
6930
6931 if string(gotBody) != wantBody {
6932 t.Errorf("%q. body\ngot\n%q\nwant\n%q", badTE, gotBody, wantBody)
6933 }
6934 }
6935 }
6936
6937
6938 func TestContentEncodingNoSniffing(t *testing.T) {
6939 run(t, testContentEncodingNoSniffing, http3SkippedMode)
6940 }
6941 func testContentEncodingNoSniffing(t *testing.T, mode testMode) {
6942 type setting struct {
6943 name string
6944 body []byte
6945
6946
6947
6948
6949 contentEncoding any
6950 wantContentType string
6951 }
6952
6953 settings := []*setting{
6954 {
6955 name: "gzip content-encoding, gzipped",
6956 contentEncoding: "application/gzip",
6957 wantContentType: "",
6958 body: func() []byte {
6959 buf := new(bytes.Buffer)
6960 gzw := gzip.NewWriter(buf)
6961 gzw.Write([]byte("doctype html><p>Hello</p>"))
6962 gzw.Close()
6963 return buf.Bytes()
6964 }(),
6965 },
6966 {
6967 name: "zlib content-encoding, zlibbed",
6968 contentEncoding: "application/zlib",
6969 wantContentType: "",
6970 body: func() []byte {
6971 buf := new(bytes.Buffer)
6972 zw := zlib.NewWriter(buf)
6973 zw.Write([]byte("doctype html><p>Hello</p>"))
6974 zw.Close()
6975 return buf.Bytes()
6976 }(),
6977 },
6978 {
6979 name: "no content-encoding",
6980 wantContentType: "application/x-gzip",
6981 body: func() []byte {
6982 buf := new(bytes.Buffer)
6983 gzw := gzip.NewWriter(buf)
6984 gzw.Write([]byte("doctype html><p>Hello</p>"))
6985 gzw.Close()
6986 return buf.Bytes()
6987 }(),
6988 },
6989 {
6990 name: "phony content-encoding",
6991 contentEncoding: "foo/bar",
6992 body: []byte("doctype html><p>Hello</p>"),
6993 },
6994 {
6995 name: "empty but set content-encoding",
6996 contentEncoding: "",
6997 wantContentType: "audio/mpeg",
6998 body: []byte("ID3"),
6999 },
7000 }
7001
7002 for _, tt := range settings {
7003 t.Run(tt.name, func(t *testing.T) {
7004 cst := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, r *Request) {
7005 if tt.contentEncoding != nil {
7006 rw.Header().Set("Content-Encoding", tt.contentEncoding.(string))
7007 }
7008 rw.Write(tt.body)
7009 }))
7010
7011 res, err := cst.c.Get(cst.ts.URL)
7012 if err != nil {
7013 t.Fatalf("Failed to fetch URL: %v", err)
7014 }
7015 defer res.Body.Close()
7016
7017 if g, w := res.Header.Get("Content-Encoding"), tt.contentEncoding; g != w {
7018 if w != nil {
7019 t.Errorf("Content-Encoding mismatch\n\tgot: %q\n\twant: %q", g, w)
7020 } else if g != "" {
7021 t.Errorf("Unexpected Content-Encoding %q", g)
7022 }
7023 }
7024
7025 if g, w := res.Header.Get("Content-Type"), tt.wantContentType; g != w {
7026 t.Errorf("Content-Type mismatch\n\tgot: %q\n\twant: %q", g, w)
7027 }
7028 })
7029 }
7030 }
7031
7032
7033
7034 func TestTimeoutHandlerSuperfluousLogs(t *testing.T) {
7035 run(t, testTimeoutHandlerSuperfluousLogs, []testMode{http1Mode})
7036 }
7037 func testTimeoutHandlerSuperfluousLogs(t *testing.T, mode testMode) {
7038 if testing.Short() {
7039 t.Skip("skipping in short mode")
7040 }
7041
7042 pc, curFile, _, _ := runtime.Caller(0)
7043 curFileBaseName := filepath.Base(curFile)
7044 testFuncName := runtime.FuncForPC(pc).Name()
7045
7046 timeoutMsg := "timed out here!"
7047
7048 tests := []struct {
7049 name string
7050 mustTimeout bool
7051 wantResp string
7052 }{
7053 {
7054 name: "return before timeout",
7055 wantResp: "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n",
7056 },
7057 {
7058 name: "return after timeout",
7059 mustTimeout: true,
7060 wantResp: fmt.Sprintf("HTTP/1.1 503 Service Unavailable\r\nContent-Length: %d\r\n\r\n%s",
7061 len(timeoutMsg), timeoutMsg),
7062 },
7063 }
7064
7065 for _, tt := range tests {
7066 t.Run(tt.name, func(t *testing.T) {
7067 exitHandler := make(chan bool, 1)
7068 defer close(exitHandler)
7069 lastLine := make(chan int, 1)
7070
7071 sh := HandlerFunc(func(w ResponseWriter, r *Request) {
7072 w.WriteHeader(404)
7073 w.WriteHeader(404)
7074 w.WriteHeader(404)
7075 w.WriteHeader(404)
7076 _, _, line, _ := runtime.Caller(0)
7077 lastLine <- line
7078 <-exitHandler
7079 })
7080
7081 if !tt.mustTimeout {
7082 exitHandler <- true
7083 }
7084
7085 logBuf := new(strings.Builder)
7086 srvLog := log.New(logBuf, "", 0)
7087
7088 dur := 20 * time.Millisecond
7089 if !tt.mustTimeout {
7090
7091 dur = 10 * time.Second
7092 }
7093 th := TimeoutHandler(sh, dur, timeoutMsg)
7094 cst := newClientServerTest(t, mode, th, optWithServerLog(srvLog))
7095 defer cst.close()
7096
7097 res, err := cst.c.Get(cst.ts.URL)
7098 if err != nil {
7099 t.Fatalf("Unexpected error: %v", err)
7100 }
7101
7102
7103
7104 res.Header.Del("Date")
7105 res.Header.Del("Content-Type")
7106
7107
7108 blob, _ := httputil.DumpResponse(res, true)
7109 if g, w := string(blob), tt.wantResp; g != w {
7110 t.Errorf("Response mismatch\nGot\n%q\n\nWant\n%q", g, w)
7111 }
7112
7113
7114
7115 logEntries := strings.Split(strings.TrimSpace(logBuf.String()), "\n")
7116 if g, w := len(logEntries), 3; g != w {
7117 blob, _ := json.MarshalIndent(logEntries, "", " ")
7118 t.Fatalf("Server logs count mismatch\ngot %d, want %d\n\nGot\n%s\n", g, w, blob)
7119 }
7120
7121 lastSpuriousLine := <-lastLine
7122 firstSpuriousLine := lastSpuriousLine - 3
7123
7124
7125 for i, logEntry := range logEntries {
7126 wantLine := firstSpuriousLine + i
7127 pat := fmt.Sprintf("^http: superfluous response.WriteHeader call from %s.func\\d+.\\d+ \\(%s:%d\\)$",
7128 testFuncName, curFileBaseName, wantLine)
7129 re := regexp.MustCompile(pat)
7130 if !re.MatchString(logEntry) {
7131 t.Errorf("Log entry mismatch\n\t%s\ndoes not match\n\t%s", logEntry, pat)
7132 }
7133 }
7134 })
7135 }
7136 }
7137
7138
7139
7140
7141 func fetchWireResponse(host string, http1ReqBody []byte) ([]byte, error) {
7142 conn, err := net.Dial("tcp", host)
7143 if err != nil {
7144 return nil, err
7145 }
7146 defer conn.Close()
7147
7148 if _, err := conn.Write(http1ReqBody); err != nil {
7149 return nil, err
7150 }
7151 return io.ReadAll(conn)
7152 }
7153
7154 func BenchmarkResponseStatusLine(b *testing.B) {
7155 b.ReportAllocs()
7156 b.RunParallel(func(pb *testing.PB) {
7157 bw := bufio.NewWriter(io.Discard)
7158 var buf3 [3]byte
7159 for pb.Next() {
7160 Export_writeStatusLine(bw, true, 200, buf3[:])
7161 }
7162 })
7163 }
7164
7165 func TestDisableKeepAliveUpgrade(t *testing.T) {
7166 run(t, testDisableKeepAliveUpgrade, []testMode{http1Mode})
7167 }
7168 func testDisableKeepAliveUpgrade(t *testing.T, mode testMode) {
7169 if testing.Short() {
7170 t.Skip("skipping in short mode")
7171 }
7172
7173 s := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
7174 w.Header().Set("Connection", "Upgrade")
7175 w.Header().Set("Upgrade", "someProto")
7176 w.WriteHeader(StatusSwitchingProtocols)
7177 c, buf, err := w.(Hijacker).Hijack()
7178 if err != nil {
7179 return
7180 }
7181 defer c.Close()
7182
7183
7184
7185 io.Copy(c, buf)
7186 }), func(ts *httptest.Server) {
7187 ts.Config.SetKeepAlivesEnabled(false)
7188 }).ts
7189
7190 cl := s.Client()
7191 cl.Transport.(*Transport).DisableKeepAlives = true
7192
7193 resp, err := cl.Get(s.URL)
7194 if err != nil {
7195 t.Fatalf("failed to perform request: %v", err)
7196 }
7197 defer resp.Body.Close()
7198
7199 if resp.StatusCode != StatusSwitchingProtocols {
7200 t.Fatalf("unexpected status code: %v", resp.StatusCode)
7201 }
7202
7203 rwc, ok := resp.Body.(io.ReadWriteCloser)
7204 if !ok {
7205 t.Fatalf("Response.Body is not an io.ReadWriteCloser: %T", resp.Body)
7206 }
7207
7208 _, err = rwc.Write([]byte("hello"))
7209 if err != nil {
7210 t.Fatalf("failed to write to body: %v", err)
7211 }
7212
7213 b := make([]byte, 5)
7214 _, err = io.ReadFull(rwc, b)
7215 if err != nil {
7216 t.Fatalf("failed to read from body: %v", err)
7217 }
7218
7219 if string(b) != "hello" {
7220 t.Fatalf("unexpected value read from body:\ngot: %q\nwant: %q", b, "hello")
7221 }
7222 }
7223
7224 type tlogWriter struct{ t *testing.T }
7225
7226 func (w tlogWriter) Write(p []byte) (int, error) {
7227 w.t.Log(string(p))
7228 return len(p), nil
7229 }
7230
7231 func TestWriteHeaderSwitchingProtocols(t *testing.T) {
7232 run(t, testWriteHeaderSwitchingProtocols, []testMode{http1Mode})
7233 }
7234 func testWriteHeaderSwitchingProtocols(t *testing.T, mode testMode) {
7235 const wantBody = "want"
7236 const wantUpgrade = "someProto"
7237 ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
7238 w.Header().Set("Connection", "Upgrade")
7239 w.Header().Set("Upgrade", wantUpgrade)
7240 w.WriteHeader(StatusSwitchingProtocols)
7241 NewResponseController(w).Flush()
7242
7243
7244 w.WriteHeader(200)
7245 if _, err := w.Write([]byte("x")); err == nil {
7246 t.Errorf("Write to body after 101 Switching Protocols unexpectedly succeeded")
7247 }
7248
7249 c, _, err := NewResponseController(w).Hijack()
7250 if err != nil {
7251 t.Errorf("Hijack: %v", err)
7252 return
7253 }
7254 defer c.Close()
7255 if _, err := c.Write([]byte(wantBody)); err != nil {
7256 t.Errorf("Write to hijacked body: %v", err)
7257 }
7258 }), func(ts *httptest.Server) {
7259
7260 ts.Config.ErrorLog = log.New(tlogWriter{t}, "log: ", 0)
7261 }).ts
7262
7263 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
7264 if err != nil {
7265 t.Fatalf("net.Dial: %v", err)
7266 }
7267 _, err = conn.Write([]byte("GET / HTTP/1.1\r\nHost: foo\r\n\r\n"))
7268 if err != nil {
7269 t.Fatalf("conn.Write: %v", err)
7270 }
7271 defer conn.Close()
7272
7273 r := bufio.NewReader(conn)
7274 res, err := ReadResponse(r, &Request{Method: "GET"})
7275 if err != nil {
7276 t.Fatal("ReadResponse error:", err)
7277 }
7278 if res.StatusCode != StatusSwitchingProtocols {
7279 t.Errorf("Response StatusCode=%v, want 101", res.StatusCode)
7280 }
7281 if got := res.Header.Get("Upgrade"); got != wantUpgrade {
7282 t.Errorf("Response Upgrade header = %q, want %q", got, wantUpgrade)
7283 }
7284 body, err := io.ReadAll(r)
7285 if err != nil {
7286 t.Error(err)
7287 }
7288 if string(body) != wantBody {
7289 t.Errorf("Response body = %q, want %q", string(body), wantBody)
7290 }
7291 }
7292
7293 func TestMuxRedirectRelative(t *testing.T) {
7294 setParallel(t)
7295 req, err := ReadRequest(bufio.NewReader(strings.NewReader("GET http://example.com HTTP/1.1\r\nHost: test\r\n\r\n")))
7296 if err != nil {
7297 t.Errorf("%s", err)
7298 }
7299 mux := NewServeMux()
7300 resp := httptest.NewRecorder()
7301 mux.ServeHTTP(resp, req)
7302 if got, want := resp.Header().Get("Location"), "/"; got != want {
7303 t.Errorf("Location header expected %q; got %q", want, got)
7304 }
7305 if got, want := resp.Code, StatusTemporaryRedirect; got != want {
7306 t.Errorf("Expected response code %d; got %d", want, got)
7307 }
7308 }
7309
7310
7311 func TestQuerySemicolon(t *testing.T) {
7312 t.Cleanup(func() { afterTest(t) })
7313
7314 tests := []struct {
7315 query string
7316 xNoSemicolons string
7317 xWithSemicolons string
7318 expectParseFormErr bool
7319 }{
7320 {"?a=1;x=bad&x=good", "good", "bad", true},
7321 {"?a=1;b=bad&x=good", "good", "good", true},
7322 {"?a=1%3Bx=bad&x=good%3B", "good;", "good;", false},
7323 {"?a=1;x=good;x=bad", "", "good", true},
7324 }
7325
7326 run(t, func(t *testing.T, mode testMode) {
7327 for _, tt := range tests {
7328 t.Run(tt.query+"/allow=false", func(t *testing.T) {
7329 allowSemicolons := false
7330 testQuerySemicolon(t, mode, tt.query, tt.xNoSemicolons, allowSemicolons, tt.expectParseFormErr)
7331 })
7332 t.Run(tt.query+"/allow=true", func(t *testing.T) {
7333 allowSemicolons, expectParseFormErr := true, false
7334 testQuerySemicolon(t, mode, tt.query, tt.xWithSemicolons, allowSemicolons, expectParseFormErr)
7335 })
7336 }
7337 })
7338 }
7339
7340 func testQuerySemicolon(t *testing.T, mode testMode, query string, wantX string, allowSemicolons, expectParseFormErr bool) {
7341 writeBackX := func(w ResponseWriter, r *Request) {
7342 x := r.URL.Query().Get("x")
7343 if expectParseFormErr {
7344 if err := r.ParseForm(); err == nil || !strings.Contains(err.Error(), "semicolon") {
7345 t.Errorf("expected error mentioning semicolons from ParseForm, got %v", err)
7346 }
7347 } else {
7348 if err := r.ParseForm(); err != nil {
7349 t.Errorf("expected no error from ParseForm, got %v", err)
7350 }
7351 }
7352 if got := r.FormValue("x"); x != got {
7353 t.Errorf("got %q from FormValue, want %q", got, x)
7354 }
7355 fmt.Fprintf(w, "%s", x)
7356 }
7357
7358 h := Handler(HandlerFunc(writeBackX))
7359 if allowSemicolons {
7360 h = AllowQuerySemicolons(h)
7361 }
7362
7363 logBuf := &strings.Builder{}
7364 ts := newClientServerTest(t, mode, h, func(ts *httptest.Server) {
7365 ts.Config.ErrorLog = log.New(logBuf, "", 0)
7366 }).ts
7367
7368 req, _ := NewRequest("GET", ts.URL+query, nil)
7369 res, err := ts.Client().Do(req)
7370 if err != nil {
7371 t.Fatal(err)
7372 }
7373 slurp, _ := io.ReadAll(res.Body)
7374 res.Body.Close()
7375 if got, want := res.StatusCode, 200; got != want {
7376 t.Errorf("Status = %d; want = %d", got, want)
7377 }
7378 if got, want := string(slurp), wantX; got != want {
7379 t.Errorf("Body = %q; want = %q", got, want)
7380 }
7381 }
7382
7383 func TestMaxBytesHandler(t *testing.T) {
7384
7385 defer afterTest(t)
7386
7387 for _, maxSize := range []int64{100, 1_000, 1_000_000} {
7388 for _, requestSize := range []int64{100, 1_000, 1_000_000} {
7389 t.Run(fmt.Sprintf("max size %d request size %d", maxSize, requestSize),
7390 func(t *testing.T) {
7391 run(t, func(t *testing.T, mode testMode) {
7392 testMaxBytesHandler(t, mode, maxSize, requestSize)
7393 }, testNotParallel)
7394 })
7395 }
7396 }
7397 }
7398
7399 func testMaxBytesHandler(t *testing.T, mode testMode, maxSize, requestSize int64) {
7400 runTimeSensitiveTest(t, []time.Duration{
7401 1 * time.Millisecond,
7402 5 * time.Millisecond,
7403 10 * time.Millisecond,
7404 50 * time.Millisecond,
7405 100 * time.Millisecond,
7406 500 * time.Millisecond,
7407 time.Second,
7408 5 * time.Second,
7409 }, func(t *testing.T, timeout time.Duration) error {
7410 SetRSTAvoidanceDelay(t, timeout)
7411 t.Logf("set RST avoidance delay to %v", timeout)
7412
7413 var (
7414 mu sync.Mutex
7415 handlerN int64
7416 handlerErr error
7417 )
7418 echo := HandlerFunc(func(w ResponseWriter, r *Request) {
7419 mu.Lock()
7420 defer mu.Unlock()
7421 var buf bytes.Buffer
7422 handlerN, handlerErr = io.Copy(&buf, r.Body)
7423 io.Copy(w, &buf)
7424 })
7425
7426 cst := newClientServerTest(t, mode, MaxBytesHandler(echo, maxSize))
7427
7428
7429 defer cst.close()
7430 ts := cst.ts
7431 c := ts.Client()
7432
7433 body := strings.Repeat("a", int(requestSize))
7434 var wg sync.WaitGroup
7435 defer wg.Wait()
7436 getBody := func() (io.ReadCloser, error) {
7437 wg.Add(1)
7438 body := &wgReadCloser{
7439 Reader: strings.NewReader(body),
7440 wg: &wg,
7441 }
7442 return body, nil
7443 }
7444 reqBody, _ := getBody()
7445 req, err := NewRequest("POST", ts.URL, reqBody)
7446 if err != nil {
7447 reqBody.Close()
7448 t.Fatal(err)
7449 }
7450 req.ContentLength = int64(len(body))
7451 req.GetBody = getBody
7452 req.Header.Set("Content-Type", "text/plain")
7453
7454 var buf strings.Builder
7455 res, err := c.Do(req)
7456 if err != nil {
7457 return fmt.Errorf("unexpected connection error: %v", err)
7458 } else {
7459 _, err = io.Copy(&buf, res.Body)
7460 res.Body.Close()
7461 if err != nil {
7462 return fmt.Errorf("unexpected read error: %v", err)
7463 }
7464 }
7465
7466
7467
7468
7469 mu.Lock()
7470 defer mu.Unlock()
7471 if handlerN > maxSize {
7472 t.Errorf("expected max request body %d; got %d", maxSize, handlerN)
7473 }
7474 if requestSize > maxSize && handlerErr == nil {
7475 t.Error("expected error on handler side; got nil")
7476 }
7477 if requestSize <= maxSize {
7478 if handlerErr != nil {
7479 t.Errorf("%d expected nil error on handler side; got %v", requestSize, handlerErr)
7480 }
7481 if handlerN != requestSize {
7482 t.Errorf("expected request of size %d; got %d", requestSize, handlerN)
7483 }
7484 }
7485 if buf.Len() != int(handlerN) {
7486 t.Errorf("expected echo of size %d; got %d", handlerN, buf.Len())
7487 }
7488
7489 return nil
7490 })
7491 }
7492
7493 func TestEarlyHints(t *testing.T) {
7494 ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
7495 h := w.Header()
7496 h.Add("Link", "</style.css>; rel=preload; as=style")
7497 h.Add("Link", "</script.js>; rel=preload; as=script")
7498 w.WriteHeader(StatusEarlyHints)
7499
7500 h.Add("Link", "</foo.js>; rel=preload; as=script")
7501 w.WriteHeader(StatusEarlyHints)
7502
7503 w.Write([]byte("stuff"))
7504 }))
7505
7506 got := ht.rawResponse("GET / HTTP/1.1\nHost: golang.org")
7507 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: "
7508 if !strings.Contains(got, expected) {
7509 t.Errorf("unexpected response; got %q; should start by %q", got, expected)
7510 }
7511 }
7512 func TestProcessing(t *testing.T) {
7513 ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
7514 w.WriteHeader(StatusProcessing)
7515 w.Write([]byte("stuff"))
7516 }))
7517
7518 got := ht.rawResponse("GET / HTTP/1.1\nHost: golang.org")
7519 expected := "HTTP/1.1 102 Processing\r\n\r\nHTTP/1.1 200 OK\r\nDate: "
7520 if !strings.Contains(got, expected) {
7521 t.Errorf("unexpected response; got %q; should start by %q", got, expected)
7522 }
7523 }
7524
7525 func TestParseFormCleanup(t *testing.T) { run(t, testParseFormCleanup, http3SkippedMode) }
7526 func testParseFormCleanup(t *testing.T, mode testMode) {
7527 if mode == http2Mode {
7528 t.Skip("https://go.dev/issue/20253")
7529 }
7530
7531 const maxMemory = 1024
7532 const key = "file"
7533
7534 if runtime.GOOS == "windows" {
7535
7536 t.Skip("https://go.dev/issue/25965")
7537 }
7538
7539 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
7540 r.ParseMultipartForm(maxMemory)
7541 f, _, err := r.FormFile(key)
7542 if err != nil {
7543 t.Errorf("r.FormFile(%q) = %v", key, err)
7544 return
7545 }
7546 of, ok := f.(*os.File)
7547 if !ok {
7548 t.Errorf("r.FormFile(%q) returned type %T, want *os.File", key, f)
7549 return
7550 }
7551 w.Write([]byte(of.Name()))
7552 }))
7553
7554 fBuf := new(bytes.Buffer)
7555 mw := multipart.NewWriter(fBuf)
7556 mf, err := mw.CreateFormFile(key, "myfile.txt")
7557 if err != nil {
7558 t.Fatal(err)
7559 }
7560 if _, err := mf.Write(bytes.Repeat([]byte("A"), maxMemory*2)); err != nil {
7561 t.Fatal(err)
7562 }
7563 if err := mw.Close(); err != nil {
7564 t.Fatal(err)
7565 }
7566 req, err := NewRequest("POST", cst.ts.URL, fBuf)
7567 if err != nil {
7568 t.Fatal(err)
7569 }
7570 req.Header.Set("Content-Type", mw.FormDataContentType())
7571 res, err := cst.c.Do(req)
7572 if err != nil {
7573 t.Fatal(err)
7574 }
7575 defer res.Body.Close()
7576 fname, err := io.ReadAll(res.Body)
7577 if err != nil {
7578 t.Fatal(err)
7579 }
7580 cst.close()
7581 if _, err := os.Stat(string(fname)); !errors.Is(err, os.ErrNotExist) {
7582 t.Errorf("file %q exists after HTTP handler returned", string(fname))
7583 }
7584 }
7585
7586 func TestHeadBody(t *testing.T) {
7587 const identityMode = false
7588 const chunkedMode = true
7589 run(t, func(t *testing.T, mode testMode) {
7590 t.Run("identity", func(t *testing.T) { testHeadBody(t, mode, identityMode, "HEAD") })
7591 t.Run("chunked", func(t *testing.T) { testHeadBody(t, mode, chunkedMode, "HEAD") })
7592 })
7593 }
7594
7595 func TestGetBody(t *testing.T) {
7596 const identityMode = false
7597 const chunkedMode = true
7598 run(t, func(t *testing.T, mode testMode) {
7599 t.Run("identity", func(t *testing.T) { testHeadBody(t, mode, identityMode, "GET") })
7600 t.Run("chunked", func(t *testing.T) { testHeadBody(t, mode, chunkedMode, "GET") })
7601 })
7602 }
7603
7604 func testHeadBody(t *testing.T, mode testMode, chunked bool, method string) {
7605 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
7606 b, err := io.ReadAll(r.Body)
7607 if err != nil {
7608 t.Errorf("server reading body: %v", err)
7609 return
7610 }
7611 w.Header().Set("X-Request-Body", string(b))
7612 w.Header().Set("Content-Length", "0")
7613 }))
7614 defer cst.close()
7615 for _, reqBody := range []string{
7616 "",
7617 "",
7618 "request_body",
7619 "",
7620 } {
7621 var bodyReader io.Reader
7622 if reqBody != "" {
7623 bodyReader = strings.NewReader(reqBody)
7624 if chunked {
7625 bodyReader = bufio.NewReader(bodyReader)
7626 }
7627 }
7628 req, err := NewRequest(method, cst.ts.URL, bodyReader)
7629 if err != nil {
7630 t.Fatal(err)
7631 }
7632 res, err := cst.c.Do(req)
7633 if err != nil {
7634 t.Fatal(err)
7635 }
7636 res.Body.Close()
7637 if got, want := res.StatusCode, 200; got != want {
7638 t.Errorf("%v request with %d-byte body: StatusCode = %v, want %v", method, len(reqBody), got, want)
7639 }
7640 if got, want := res.Header.Get("X-Request-Body"), reqBody; got != want {
7641 t.Errorf("%v request with %d-byte body: handler read body %q, want %q", method, len(reqBody), got, want)
7642 }
7643 }
7644 }
7645
7646
7647
7648 func TestDisableContentLength(t *testing.T) { run(t, testDisableContentLength) }
7649 func testDisableContentLength(t *testing.T, mode testMode) {
7650 noCL := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
7651 w.Header()["Content-Length"] = nil
7652 fmt.Fprintf(w, "OK")
7653 }))
7654
7655 res, err := noCL.c.Get(noCL.ts.URL)
7656 if err != nil {
7657 t.Fatal(err)
7658 }
7659 if got, haveCL := res.Header["Content-Length"]; haveCL {
7660 t.Errorf("Unexpected Content-Length: %q", got)
7661 }
7662 if err := res.Body.Close(); err != nil {
7663 t.Fatal(err)
7664 }
7665
7666 withCL := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
7667 fmt.Fprintf(w, "OK")
7668 }))
7669
7670 res, err = withCL.c.Get(withCL.ts.URL)
7671 if err != nil {
7672 t.Fatal(err)
7673 }
7674
7675 if got := res.Header.Get("Content-Length"); got != "2" && mode != http3Mode {
7676 t.Errorf("Content-Length: %q; want 2", got)
7677 }
7678 if err := res.Body.Close(); err != nil {
7679 t.Fatal(err)
7680 }
7681 }
7682
7683 func TestErrorContentLength(t *testing.T) { run(t, testErrorContentLength) }
7684 func testErrorContentLength(t *testing.T, mode testMode) {
7685 const errorBody = "an error occurred"
7686 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
7687 w.Header().Set("Content-Length", "1000")
7688 Error(w, errorBody, 400)
7689 }))
7690 res, err := cst.c.Get(cst.ts.URL)
7691 if err != nil {
7692 t.Fatalf("Get(%q) = %v", cst.ts.URL, err)
7693 }
7694 defer res.Body.Close()
7695 body, err := io.ReadAll(res.Body)
7696 if err != nil {
7697 t.Fatalf("io.ReadAll(res.Body) = %v", err)
7698 }
7699 if string(body) != errorBody+"\n" {
7700 t.Fatalf("read body: %q, want %q", string(body), errorBody)
7701 }
7702 }
7703
7704 func TestError(t *testing.T) {
7705 w := httptest.NewRecorder()
7706 w.Header().Set("Content-Length", "1")
7707 w.Header().Set("X-Content-Type-Options", "scratch and sniff")
7708 w.Header().Set("Other", "foo")
7709 Error(w, "oops", 432)
7710
7711 h := w.Header()
7712 for _, hdr := range []string{"Content-Length"} {
7713 if v, ok := h[hdr]; ok {
7714 t.Errorf("%s: %q, want not present", hdr, v)
7715 }
7716 }
7717 if v := h.Get("Content-Type"); v != "text/plain; charset=utf-8" {
7718 t.Errorf("Content-Type: %q, want %q", v, "text/plain; charset=utf-8")
7719 }
7720 if v := h.Get("X-Content-Type-Options"); v != "nosniff" {
7721 t.Errorf("X-Content-Type-Options: %q, want %q", v, "nosniff")
7722 }
7723 }
7724
7725 func TestServerReadAfterWriteHeader100Continue(t *testing.T) {
7726 run(t, testServerReadAfterWriteHeader100Continue)
7727 }
7728 func testServerReadAfterWriteHeader100Continue(t *testing.T, mode testMode) {
7729 t.Skip("https://go.dev/issue/67555")
7730 body := []byte("body")
7731 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
7732 w.WriteHeader(200)
7733 NewResponseController(w).Flush()
7734 io.ReadAll(r.Body)
7735 w.Write(body)
7736 }), func(tr *Transport) {
7737 tr.ExpectContinueTimeout = 24 * time.Hour
7738 })
7739
7740 req, _ := NewRequest("GET", cst.ts.URL, strings.NewReader("body"))
7741 req.Header.Set("Expect", "100-continue")
7742 res, err := cst.c.Do(req)
7743 if err != nil {
7744 t.Fatalf("Get(%q) = %v", cst.ts.URL, err)
7745 }
7746 defer res.Body.Close()
7747 got, err := io.ReadAll(res.Body)
7748 if err != nil {
7749 t.Fatalf("io.ReadAll(res.Body) = %v", err)
7750 }
7751 if !bytes.Equal(got, body) {
7752 t.Fatalf("response body = %q, want %q", got, body)
7753 }
7754 }
7755
7756 func TestServerReadAfterHandlerDone100Continue(t *testing.T) {
7757 run(t, testServerReadAfterHandlerDone100Continue)
7758 }
7759 func testServerReadAfterHandlerDone100Continue(t *testing.T, mode testMode) {
7760 t.Skip("https://go.dev/issue/67555")
7761 readyc := make(chan struct{})
7762 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
7763 go func() {
7764 <-readyc
7765 io.ReadAll(r.Body)
7766 <-readyc
7767 }()
7768 }), func(tr *Transport) {
7769 tr.ExpectContinueTimeout = 24 * time.Hour
7770 })
7771
7772 req, _ := NewRequest("GET", cst.ts.URL, strings.NewReader("body"))
7773 req.Header.Set("Expect", "100-continue")
7774 res, err := cst.c.Do(req)
7775 if err != nil {
7776 t.Fatalf("Get(%q) = %v", cst.ts.URL, err)
7777 }
7778 res.Body.Close()
7779 readyc <- struct{}{}
7780 readyc <- struct{}{}
7781 }
7782
7783 func TestServerReadAfterHandlerAbort100Continue(t *testing.T) {
7784 run(t, testServerReadAfterHandlerAbort100Continue)
7785 }
7786 func testServerReadAfterHandlerAbort100Continue(t *testing.T, mode testMode) {
7787 t.Skip("https://go.dev/issue/67555")
7788 readyc := make(chan struct{})
7789 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
7790 go func() {
7791 <-readyc
7792 io.ReadAll(r.Body)
7793 <-readyc
7794 }()
7795 panic(ErrAbortHandler)
7796 }), func(tr *Transport) {
7797 tr.ExpectContinueTimeout = 24 * time.Hour
7798 })
7799
7800 req, _ := NewRequest("GET", cst.ts.URL, strings.NewReader("body"))
7801 req.Header.Set("Expect", "100-continue")
7802 res, err := cst.c.Do(req)
7803 if err == nil {
7804 res.Body.Close()
7805 }
7806 readyc <- struct{}{}
7807 readyc <- struct{}{}
7808 }
7809
7810
7811 func TestServerExpect100ContinueUnreadBody(t *testing.T) {
7812 run(t, testServerExpect100ContinueUnreadBody)
7813 }
7814 func testServerExpect100ContinueUnreadBody(t *testing.T, mode testMode) {
7815 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
7816 w.WriteHeader(StatusOK)
7817
7818
7819 io.ReadAll(r.Body)
7820 }))
7821
7822 req, _ := NewRequest("POST", cst.ts.URL, strings.NewReader("some body"))
7823 req.Header.Set("Expect", "100-continue")
7824
7825
7826 cst.c.Timeout = 2 * time.Second
7827 cst.tr.ExpectContinueTimeout = 10 * time.Second
7828
7829 resp, err := cst.c.Do(req)
7830 if err != nil {
7831 t.Fatalf("Request failed: %v (likely due to hang)", err)
7832 }
7833 defer resp.Body.Close()
7834
7835 if resp.StatusCode != StatusOK {
7836 t.Errorf("expected 200 OK, got %v", resp.Status)
7837 }
7838 }
7839
7840 func TestInvalidChunkedBodies(t *testing.T) {
7841 for _, test := range []struct {
7842 name string
7843 b string
7844 }{{
7845 name: "bare LF in chunk size",
7846 b: "1\na\r\n0\r\n\r\n",
7847 }, {
7848 name: "bare LF at body end",
7849 b: "1\r\na\r\n0\r\n\n",
7850 }} {
7851 t.Run(test.name, func(t *testing.T) {
7852 reqc := make(chan error)
7853 ts := newClientServerTest(t, http1Mode, HandlerFunc(func(w ResponseWriter, r *Request) {
7854 got, err := io.ReadAll(r.Body)
7855 if err == nil {
7856 t.Logf("read body: %q", got)
7857 }
7858 reqc <- err
7859 })).ts
7860
7861 serverURL, err := url.Parse(ts.URL)
7862 if err != nil {
7863 t.Fatal(err)
7864 }
7865
7866 conn, err := net.Dial("tcp", serverURL.Host)
7867 if err != nil {
7868 t.Fatal(err)
7869 }
7870
7871 if _, err := conn.Write([]byte(
7872 "POST / HTTP/1.1\r\n" +
7873 "Host: localhost\r\n" +
7874 "Transfer-Encoding: chunked\r\n" +
7875 "Connection: close\r\n" +
7876 "\r\n" +
7877 test.b)); err != nil {
7878 t.Fatal(err)
7879 }
7880 conn.(*net.TCPConn).CloseWrite()
7881
7882 if err := <-reqc; err == nil {
7883 t.Errorf("server handler: io.ReadAll(r.Body) succeeded, want error")
7884 }
7885 })
7886 }
7887 }
7888
7889
7890 func TestServerTLSNextProtos(t *testing.T) {
7891 run(t, testServerTLSNextProtos, []testMode{https1Mode, http2Mode})
7892 }
7893 func testServerTLSNextProtos(t *testing.T, mode testMode) {
7894 CondSkipHTTP2(t)
7895
7896 cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey)
7897 if err != nil {
7898 t.Fatal(err)
7899 }
7900 leafCert, err := x509.ParseCertificate(cert.Certificate[0])
7901 if err != nil {
7902 t.Fatal(err)
7903 }
7904 certpool := x509.NewCertPool()
7905 certpool.AddCert(leafCert)
7906
7907 protos := new(Protocols)
7908 switch mode {
7909 case https1Mode:
7910 protos.SetHTTP1(true)
7911 case http2Mode:
7912 protos.SetHTTP2(true)
7913 }
7914
7915 wantNextProtos := []string{"http/1.1", "h2", "other"}
7916 nextProtos := slices.Clone(wantNextProtos)
7917
7918
7919 srv := &Server{
7920 TLSConfig: &tls.Config{
7921 Certificates: []tls.Certificate{cert},
7922 NextProtos: nextProtos,
7923 },
7924 Handler: HandlerFunc(func(w ResponseWriter, req *Request) {}),
7925 Protocols: protos,
7926 }
7927 tr := &Transport{
7928 TLSClientConfig: &tls.Config{
7929 RootCAs: certpool,
7930 NextProtos: nextProtos,
7931 },
7932 Protocols: protos,
7933 }
7934
7935 listener := newLocalListener(t)
7936 srvc := make(chan error, 1)
7937 go func() {
7938 srvc <- srv.ServeTLS(listener, "", "")
7939 }()
7940 t.Cleanup(func() {
7941 srv.Close()
7942 <-srvc
7943 })
7944
7945 client := &Client{Transport: tr}
7946 resp, err := client.Get("https://" + listener.Addr().String())
7947 if err != nil {
7948 t.Fatal(err)
7949 }
7950 resp.Body.Close()
7951
7952 if !slices.Equal(nextProtos, wantNextProtos) {
7953 t.Fatalf("after running test: original NextProtos slice = %v, want %v", nextProtos, wantNextProtos)
7954 }
7955 }
7956
7957
7958
7959 func TestServerHTTP2Disabled(t *testing.T) {
7960 synctest.Test(t, func(t *testing.T) {
7961 li := fakeNetListen()
7962 srv := &Server{}
7963 srv.Protocols = new(Protocols)
7964 srv.Protocols.SetHTTP1(true)
7965 go srv.ServeTLS(li, "", "")
7966 synctest.Wait()
7967 srv.Shutdown(t.Context())
7968 })
7969 }
7970
7971 func TestServerConnectionReuse(t *testing.T) {
7972 for _, test := range []struct {
7973 name string
7974 message []string
7975 handler HandlerFunc
7976 continueBodySize int
7977 want100Continue bool
7978 wantResponse int
7979 wantReused bool
7980 skip string
7981 }{{
7982 name: "small body",
7983 message: []string{
7984 "POST / HTTP/1.1",
7985 "Host: example.tld",
7986 "Content-Length: 1",
7987 "",
7988 "x",
7989 },
7990 wantResponse: 200,
7991 wantReused: true,
7992 }, {
7993 name: "large body",
7994 message: []string{
7995 "POST / HTTP/1.1",
7996 "Host: example.tld",
7997 "Content-Length: 300000",
7998 "",
7999
8000 },
8001 wantResponse: 200,
8002 wantReused: false,
8003 }, {
8004 name: "small body full duplex",
8005 message: []string{
8006 "POST / HTTP/1.1",
8007 "Host: example.tld",
8008 "Content-Length: 1",
8009 "",
8010 "x",
8011 },
8012 handler: func(w ResponseWriter, req *Request) {
8013
8014
8015 NewResponseController(w).EnableFullDuplex()
8016 },
8017 wantResponse: 200,
8018 wantReused: true,
8019 }, {
8020 name: "large body full duplex",
8021 message: []string{
8022 "POST / HTTP/1.1",
8023 "Host: example.tld",
8024 "Content-Length: 300000",
8025 "",
8026
8027 },
8028 handler: func(w ResponseWriter, req *Request) {
8029
8030
8031 NewResponseController(w).EnableFullDuplex()
8032 },
8033 wantResponse: 200,
8034 wantReused: false,
8035 }, {
8036
8037
8038
8039
8040
8041
8042 skip: "https://go.dev/issue/75933",
8043
8044 name: "100-continue unconsumed small body",
8045 message: []string{
8046 "POST / HTTP/1.1",
8047 "Host: example.tld",
8048 "Expect: 100-continue",
8049 "Content-Length: 1",
8050 "",
8051
8052 },
8053 want100Continue: false,
8054 wantResponse: 200,
8055 wantReused: true,
8056 }, {
8057 name: "100-continue unconsumed large body",
8058 message: []string{
8059 "POST / HTTP/1.1",
8060 "Host: example.tld",
8061 "Expect: 100-continue",
8062 "Content-Length: 300000",
8063 "",
8064
8065 },
8066 want100Continue: false,
8067 wantResponse: 200,
8068 wantReused: false,
8069 }, {
8070 name: "100-continue consumed small body",
8071 message: []string{
8072 "POST / HTTP/1.1",
8073 "Host: example.tld",
8074 "Expect: 100-continue",
8075 "Content-Length: 1",
8076 "",
8077 },
8078 handler: func(w ResponseWriter, req *Request) {
8079 io.Copy(io.Discard, req.Body)
8080 },
8081 want100Continue: true,
8082 continueBodySize: 1,
8083 wantResponse: 200,
8084 wantReused: true,
8085 }, {
8086 name: "small wrapped body",
8087 message: []string{
8088 "POST / HTTP/1.1",
8089 "Host: example.tld",
8090 "Content-Length: 1",
8091 "",
8092 "x",
8093 },
8094 handler: func(w ResponseWriter, req *Request) {
8095
8096
8097 NewResponseController(w).EnableFullDuplex()
8098
8099
8100 req.Body = struct{ io.ReadCloser }{req.Body}
8101 },
8102 wantResponse: 200,
8103 wantReused: true,
8104 }, {
8105 name: "large wrapped body",
8106 message: []string{
8107 "POST / HTTP/1.1",
8108 "Host: example.tld",
8109 "Content-Length: 300000",
8110 "",
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: false,
8122 }} {
8123 t.Run(test.name, func(t *testing.T) {
8124 if test.skip != "" {
8125 t.Skip(test.skip)
8126 }
8127 synctest.Test(t, func(t *testing.T) {
8128 st := newHTTP1ServerTest(t, test.handler)
8129 conn := st.dial()
8130 conn.writeMessage(test.message...)
8131 resp := conn.readResponse()
8132 if got, want := resp.StatusCode == 100, test.want100Continue; got != want {
8133 t.Fatalf("100-Continue response: %v, want %v", got, want)
8134 }
8135 if resp.StatusCode == 100 {
8136 conn.conn.Write(bytes.Repeat([]byte("x"), test.continueBodySize))
8137 resp = conn.readResponse()
8138 }
8139 if got, want := resp.StatusCode, test.wantResponse; got != want {
8140 t.Fatalf("got response %v, want %v", got, want)
8141 }
8142 if test.wantReused {
8143 conn.wantIdle()
8144 } else {
8145 conn.wantClosed()
8146 }
8147 })
8148 })
8149 }
8150 }
8151
8152
8153
8154
8155 func TestServerRequestBodyCloseAfterPartialRead(t *testing.T) {
8156 synctest.Test(t, func(t *testing.T) {
8157 closeErr := make(chan error, 1)
8158 st := newHTTP1ServerTest(t, func(w ResponseWriter, req *Request) {
8159
8160 if _, err := io.ReadFull(req.Body, make([]byte, 2)); err != nil {
8161 closeErr <- fmt.Errorf("reading request body: %v", err)
8162 return
8163 }
8164 closeErr <- req.Body.Close()
8165 })
8166 conn := st.dial()
8167 conn.writeMessage(
8168 "POST / HTTP/1.1",
8169 "Host: example.tld",
8170 "Content-Length: 4",
8171 "",
8172 "test",
8173 )
8174 if got, want := conn.readResponse().StatusCode, 200; got != want {
8175 t.Fatalf("got response %v, want %v", got, want)
8176 }
8177 if err := <-closeErr; err != nil {
8178 t.Errorf("Request.Body.Close() = %v, want nil", err)
8179 }
8180 })
8181 }
8182
View as plain text