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