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