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