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