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