Source file src/net/http/internal/http3/server_test.go

     1  // Copyright 2024 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package http3
     6  
     7  import (
     8  	"errors"
     9  	"fmt"
    10  	"io"
    11  	"maps"
    12  	"net/http"
    13  	"net/netip"
    14  	"net/url"
    15  	"os"
    16  	"reflect"
    17  	"slices"
    18  	"strconv"
    19  	"strings"
    20  	"sync"
    21  	"testing"
    22  	"testing/synctest"
    23  	"time"
    24  
    25  	"golang.org/x/net/quic"
    26  )
    27  
    28  // requestHeader is a helper function to make sure that all required
    29  // pseudo-headers exist in an http.Header used for a request. Per
    30  // https://www.rfc-editor.org/rfc/rfc9114.html#name-request-pseudo-header-field:
    31  // "All HTTP/3 requests MUST include exactly one value for the :method,
    32  // :scheme, and :path pseudo-header fields, unless the request is a CONNECT
    33  // request;"
    34  func requestHeader(h http.Header) http.Header {
    35  	minimalHeader := http.Header{
    36  		":method": {"GET"},
    37  		":scheme": {"https"},
    38  		":path":   {"/"},
    39  	}
    40  	maps.Copy(minimalHeader, h)
    41  	return minimalHeader
    42  }
    43  
    44  func TestServerReceivePushStream(t *testing.T) {
    45  	// "[...] if a server receives a client-initiated push stream,
    46  	// this MUST be treated as a connection error of type H3_STREAM_CREATION_ERROR."
    47  	// https://www.rfc-editor.org/rfc/rfc9114.html#section-6.2.2-3
    48  	synctest.Test(t, func(t *testing.T) {
    49  		ts := newTestServer(t, nil)
    50  		tc := ts.connect()
    51  		tc.newStream(streamTypePush)
    52  		tc.wantClosed("invalid client-created push stream", errH3StreamCreationError)
    53  	})
    54  }
    55  
    56  func TestServerCancelPushForUnsentPromise(t *testing.T) {
    57  	synctest.Test(t, func(t *testing.T) {
    58  		ts := newTestServer(t, nil)
    59  		tc := ts.connect()
    60  		tc.greet()
    61  
    62  		const pushID = 100
    63  		tc.control.writeVarint(int64(frameTypeCancelPush))
    64  		tc.control.writeVarint(int64(sizeVarint(pushID)))
    65  		tc.control.writeVarint(pushID)
    66  		tc.control.Flush()
    67  
    68  		tc.wantClosed("client canceled never-sent push ID", errH3IDError)
    69  	})
    70  }
    71  
    72  func TestServerHeader(t *testing.T) {
    73  	synctest.Test(t, func(t *testing.T) {
    74  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    75  			header := w.Header()
    76  			for key, values := range r.Header {
    77  				for _, value := range values {
    78  					header.Add(key, value)
    79  				}
    80  			}
    81  			w.WriteHeader(204)
    82  		}))
    83  		tc := ts.connect()
    84  		tc.greet()
    85  
    86  		reqStream := tc.newStream(streamTypeRequest)
    87  		reqStream.writeHeaders(requestHeader(http.Header{
    88  			"header-from-client": {"that", "should", "be", "echoed"},
    89  		}))
    90  		reqStream.wantSomeHeaders(http.Header{
    91  			":status":            {"204"},
    92  			"Header-From-Client": {"that", "should", "be", "echoed"},
    93  		})
    94  		reqStream.wantClosed("request is complete")
    95  	})
    96  }
    97  
    98  func TestServerHeaderSnapshot(t *testing.T) {
    99  	synctest.Test(t, func(t *testing.T) {
   100  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   101  			w.Header().Set("X-Test-Header", "original")
   102  			w.WriteHeader(200)
   103  			w.Header().Set("X-Test-Header", "modified")
   104  			w.Write([]byte("body"))
   105  		}))
   106  		tc := ts.connect()
   107  		tc.greet()
   108  
   109  		reqStream := tc.newStream(streamTypeRequest)
   110  		reqStream.writeHeaders(requestHeader(nil))
   111  		reqStream.wantSomeHeaders(http.Header{
   112  			":status":       {"200"},
   113  			"X-Test-Header": {"original"},
   114  		})
   115  		reqStream.wantData([]byte("body"))
   116  		reqStream.wantClosed("request is complete")
   117  	})
   118  }
   119  
   120  func TestServerHeaderInvalid(t *testing.T) {
   121  	tests := []struct {
   122  		name      string
   123  		header    http.Header
   124  		wantError bool
   125  	}{
   126  		{
   127  			name:      "header name with control character",
   128  			header:    http.Header{"name\nevilinjection": {"Value"}},
   129  			wantError: true,
   130  		},
   131  		{
   132  			name:      "header name with uppercase character",
   133  			header:    http.Header{"nAme": {"Value"}},
   134  			wantError: true,
   135  		},
   136  		{
   137  			name:      "pseudo-header name with control character",
   138  			header:    http.Header{":path\nevilinjection": {"Value"}},
   139  			wantError: true,
   140  		},
   141  		{
   142  			name:      "pseudo-header name with uppercase character",
   143  			header:    http.Header{":meThod": {"Value"}},
   144  			wantError: true,
   145  		},
   146  		{
   147  			name:      "header value with control character",
   148  			header:    http.Header{"name": {"Value\nEvilInjection"}},
   149  			wantError: true,
   150  		},
   151  		{
   152  			name:      "pseudo-header value with control character",
   153  			header:    http.Header{":method": {"Value\nEvilInjection"}},
   154  			wantError: true,
   155  		},
   156  		{
   157  			name:      "connection header name",
   158  			header:    http.Header{"connection": {"foo"}},
   159  			wantError: true,
   160  		},
   161  		{
   162  			name:      "keep-alive header name",
   163  			header:    http.Header{"Keep-Alive": {"foo"}},
   164  			wantError: true,
   165  		},
   166  		{
   167  			name:      "proxy-connection header name",
   168  			header:    http.Header{"proxy-connection": {"foo"}},
   169  			wantError: true,
   170  		},
   171  		{
   172  			name:      "transfer-encoding header name",
   173  			header:    http.Header{"transfer-encoding": {"foo"}},
   174  			wantError: true,
   175  		},
   176  		{
   177  			name:      "upgrade header name",
   178  			header:    http.Header{"upgrade": {"foo"}},
   179  			wantError: true,
   180  		},
   181  		{
   182  			name:      "te header name",
   183  			header:    http.Header{"te": {"foo"}},
   184  			wantError: true,
   185  		},
   186  		{
   187  			name:      "te header name with trailers value",
   188  			header:    http.Header{"te": {"trailers"}},
   189  			wantError: false,
   190  		},
   191  	}
   192  	for _, tt := range tests {
   193  		synctestSubtest(t, tt.name, func(t *testing.T) {
   194  			body := []byte("some data")
   195  			ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   196  				w.Write(body)
   197  			}))
   198  			tc := ts.connect()
   199  			tc.greet()
   200  
   201  			reqStream := tc.newStream(streamTypeRequest)
   202  			reqStream.writeHeadersRaw(requestHeader(tt.header))
   203  
   204  			if tt.wantError {
   205  				reqStream.wantError(quic.StreamError(errH3MessageError))
   206  			} else {
   207  				reqStream.wantHeaders(nil)
   208  				reqStream.wantData(body)
   209  				reqStream.wantClosed("request is complete")
   210  			}
   211  		})
   212  	}
   213  }
   214  
   215  func TestServerPseudoHeader(t *testing.T) {
   216  	synctest.Test(t, func(t *testing.T) {
   217  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   218  			// Pseudo-headers from client request should populate a specific
   219  			// field in http.Request, and should not be part of http.Request.Header.
   220  			if len(r.Header) != 0 {
   221  				t.Errorf("got %v, want request header to be empty", r.Header)
   222  			}
   223  			if r.Method != "GET" {
   224  				t.Errorf("got %v, want GET method", r.Method)
   225  			}
   226  			if r.Host != "fake.tld:1234" {
   227  				t.Errorf("got %v, want fake.tld:1234", r.Host)
   228  			}
   229  			wantURL := &url.URL{
   230  				Path:     "/some/path",
   231  				RawQuery: "query=value&query2=value2#fragment",
   232  			}
   233  			if !reflect.DeepEqual(r.URL, wantURL) {
   234  				t.Errorf("got %v, want URL to be %v", r.URL, wantURL)
   235  			}
   236  
   237  			// Conversely, server should not be able to set pseudo-headers by
   238  			// writing to the ResponseWriter's Header.
   239  			header := w.Header()
   240  			header.Add(":status", "123")
   241  			w.WriteHeader(321)
   242  		}))
   243  		tc := ts.connect()
   244  		tc.greet()
   245  
   246  		reqStream := tc.newStream(streamTypeRequest)
   247  		reqStream.writeHeaders(http.Header{
   248  			":method":    {"GET"},
   249  			":authority": {"fake.tld:1234"},
   250  			":scheme":    {"https"},
   251  			":path":      {"/some/path?query=value&query2=value2#fragment"},
   252  		})
   253  		reqStream.wantSomeHeaders(http.Header{":status": {"321"}})
   254  		reqStream.wantClosed("request is complete")
   255  
   256  		reqStream = tc.newStream(streamTypeRequest)
   257  		reqStream.writeHeaders(http.Header{}) // Missing pseudo-header.
   258  		reqStream.wantError(quic.StreamError(errH3MessageError))
   259  	})
   260  }
   261  
   262  func TestServerPseudoHeaderCount(t *testing.T) {
   263  	tests := []struct {
   264  		name      string
   265  		header    http.Header
   266  		wantError bool
   267  	}{
   268  		{
   269  			name: "missing method pseudo-header",
   270  			header: http.Header{
   271  				":scheme":    {"https"},
   272  				":path":      {"/"},
   273  				":authority": {"fake.tld:1234"},
   274  			},
   275  			wantError: true,
   276  		},
   277  		{
   278  			name: "valid pseudo-headers for non-CONNECT request",
   279  			header: http.Header{
   280  				":method": {"GET"},
   281  				":scheme": {"https"},
   282  				":path":   {"/"},
   283  			},
   284  			wantError: false,
   285  		},
   286  		{
   287  			name: "extraneous pseudo-headers for non-CONNECT request",
   288  			header: http.Header{
   289  				":method": {"GET", "GET"}, // Duplicate :method.
   290  				":scheme": {"https"},
   291  				":path":   {"/"},
   292  			},
   293  			wantError: true,
   294  		},
   295  		{
   296  			name: "missing pseudo-headers for non-CONNECT request",
   297  			header: http.Header{
   298  				":method": {"GET", "GET"},
   299  				":path":   {"/"},
   300  			},
   301  			wantError: true,
   302  		},
   303  		{
   304  			name: "valid pseudo-headers for CONNECT request",
   305  			header: http.Header{
   306  				":method":    {"CONNECT"},
   307  				":authority": {"fake.tld:1234"},
   308  			},
   309  			wantError: false,
   310  		},
   311  		{
   312  			name: "extraneous pseudo-headers for CONNECT request",
   313  			header: http.Header{
   314  				":method":    {"CONNECT"},
   315  				":authority": {"fake.tld:1234"},
   316  				":path":      {"/"}, // :path should be omitted.
   317  			},
   318  			wantError: true,
   319  		},
   320  		{
   321  			name: "missing pseudo-headers for CONNECT request",
   322  			header: http.Header{
   323  				":method": {"CONNECT"},
   324  			},
   325  			wantError: true,
   326  		},
   327  	}
   328  	for _, tt := range tests {
   329  		synctestSubtest(t, tt.name, func(t *testing.T) {
   330  			body := []byte("some data")
   331  			ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   332  				w.Write(body)
   333  			}))
   334  			tc := ts.connect()
   335  			tc.greet()
   336  
   337  			reqStream := tc.newStream(streamTypeRequest)
   338  			reqStream.writeHeaders(tt.header)
   339  
   340  			if tt.wantError {
   341  				reqStream.wantError(quic.StreamError(errH3MessageError))
   342  			} else {
   343  				reqStream.wantHeaders(nil)
   344  				reqStream.wantData(body)
   345  				reqStream.wantClosed("request is complete")
   346  			}
   347  		})
   348  	}
   349  }
   350  
   351  func TestServerInvalidHeader(t *testing.T) {
   352  	synctest.Test(t, func(t *testing.T) {
   353  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   354  			w.Header().Add("valid-name", "valid value")
   355  			// Invalid headers are skipped.
   356  			w.Header().Add("invalid name with spaces", "some value")
   357  			w.Header().Add("some-name", "invalid value with \n")
   358  			w.Header().Add("valid-name-2", "valid value 2")
   359  			w.WriteHeader(200)
   360  		}))
   361  		tc := ts.connect()
   362  		tc.greet()
   363  
   364  		reqStream := tc.newStream(streamTypeRequest)
   365  		reqStream.writeHeaders(requestHeader(nil))
   366  		reqStream.wantSomeHeaders(http.Header{
   367  			":status":      {"200"},
   368  			"Valid-Name":   {"valid value"},
   369  			"Valid-Name-2": {"valid value 2"},
   370  		})
   371  		reqStream.wantClosed("request is complete")
   372  	})
   373  }
   374  
   375  func TestServerAuthorityAndHostHeader(t *testing.T) {
   376  	for _, test := range []struct {
   377  		name     string
   378  		h        http.Header
   379  		valid    bool
   380  		wantHost string
   381  	}{{
   382  		name: "authority host mismatch",
   383  		h: http.Header{
   384  			":authority": {"example.tld"},
   385  			"host":       {"other.tld"},
   386  		},
   387  	}, {
   388  		// The RFCs aren't explicit on whether a :authority and host that
   389  		// differ only in case is a mismatch. We treat it as a mismatch because
   390  		// there doesn't seem to be a good reason not to.
   391  		name: "authority host case differs",
   392  		h: http.Header{
   393  			":authority": {"example.tld"},
   394  			"host":       {"EXAMPLE.TLD"},
   395  		},
   396  	}, {
   397  		name: "authority and multiple host",
   398  		h: http.Header{
   399  			":authority": {"example.tld"},
   400  			"host":       {"example.tld", "example.tld"},
   401  		},
   402  	}, {
   403  		name: "multiple host only",
   404  		h: http.Header{
   405  			"host": {"example.tld", "example.tld"},
   406  		},
   407  	}, {
   408  		name: "multiple authority only",
   409  		h: http.Header{
   410  			":authority": {"example.tld", "example.tld"},
   411  		},
   412  	}, {
   413  		name: "empty authority",
   414  		h: http.Header{
   415  			":authority": {""},
   416  		},
   417  	}, {
   418  		name: "invalid authority",
   419  		h: http.Header{
   420  			":authority": {"example . tld"},
   421  		},
   422  	}, {
   423  		name: "invalid host",
   424  		h: http.Header{
   425  			"host": {"example . tld"},
   426  		},
   427  	}, {
   428  		name: "authority only",
   429  		h: http.Header{
   430  			":authority": {"example.tld"},
   431  		},
   432  		valid:    true,
   433  		wantHost: "example.tld",
   434  	}, {
   435  		name: "host only",
   436  		h: http.Header{
   437  			"host": {"example.tld"},
   438  		},
   439  		valid:    true,
   440  		wantHost: "example.tld",
   441  	}, {
   442  		name: "authority host match",
   443  		h: http.Header{
   444  			":authority": {"example.tld"},
   445  			"host":       {"example.tld"},
   446  		},
   447  		valid:    true,
   448  		wantHost: "example.tld",
   449  	}, {
   450  		name: "authority host match with port",
   451  		h: http.Header{
   452  			":authority": {"example.tld:443"},
   453  			"host":       {"example.tld:443"},
   454  		},
   455  		valid:    true,
   456  		wantHost: "example.tld:443",
   457  	}, {
   458  		name: "authority host mismatch with port",
   459  		h: http.Header{
   460  			":authority": {"example.tld:80"},
   461  			"host":       {"example.tld:443"},
   462  		},
   463  	}, {
   464  		name: "userinfo in authority",
   465  		h: http.Header{
   466  			":authority": {"user:pass@example.tld"},
   467  		},
   468  	}, {
   469  		name: "userinfo in host",
   470  		h: http.Header{
   471  			"host": {"user:pass@example.tld"},
   472  		},
   473  	}, {
   474  		name:     "neither authority nor host",
   475  		h:        http.Header{},
   476  		valid:    true,
   477  		wantHost: "",
   478  	}} {
   479  		synctestSubtest(t, test.name, func(t *testing.T) {
   480  			ts := newTestServer(t, nil)
   481  			tc := ts.connect()
   482  			tc.greet()
   483  
   484  			reqStream := tc.newStream(streamTypeRequest)
   485  			reqStream.writeHeaders(requestHeader(test.h))
   486  			if test.valid {
   487  				call := tc.nextHandlerCall()
   488  				if call == nil {
   489  					t.Fatal("no server handler call; want one")
   490  				}
   491  				if got, want := call.req.Host, test.wantHost; got != want {
   492  					t.Errorf("handler got Host %q, want %q", got, want)
   493  				}
   494  				if h, ok := call.req.Header["Host"]; ok {
   495  					t.Errorf(`handler got Header["Host"] = %q, want unset`, h)
   496  				}
   497  			} else {
   498  				reqStream.wantError(quic.StreamError(errH3MessageError))
   499  			}
   500  		})
   501  	}
   502  }
   503  
   504  func TestServerInvalidStatus(t *testing.T) {
   505  	synctest.Test(t, func(t *testing.T) {
   506  		gotpanic := make(chan bool)
   507  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   508  			defer close(gotpanic)
   509  			defer func() {
   510  				if e := recover(); e != nil {
   511  					got := fmt.Sprintf("%T, %v", e, e)
   512  					want := "string, invalid WriteHeader code 0"
   513  					if got != want {
   514  						t.Errorf("unexpected panic value:\n got: %v\nwant: %v\n", got, want)
   515  					}
   516  					gotpanic <- true
   517  					// Set an explicit 503. This also tests that the
   518  					// WriteHeader call panics before it recorded that an
   519  					// explicit value was set.
   520  					w.WriteHeader(503)
   521  
   522  					// Verify that writing invalid status will not panic if a
   523  					// status is already set anyways.
   524  					w.WriteHeader(0)
   525  				}
   526  			}()
   527  			w.WriteHeader(0) // Invalid. Will panic.
   528  		}))
   529  		tc := ts.connect()
   530  		tc.greet()
   531  
   532  		reqStream := tc.newStream(streamTypeRequest)
   533  		reqStream.writeHeaders(requestHeader(nil))
   534  		if !<-gotpanic {
   535  			t.Error("expected panic in handler")
   536  		}
   537  		synctest.Wait()
   538  		reqStream.wantSomeHeaders(http.Header{
   539  			":status": {"503"},
   540  		})
   541  		reqStream.wantClosed("request is complete")
   542  	})
   543  }
   544  
   545  func TestServerHeaderLimits(t *testing.T) {
   546  	for _, test := range []struct {
   547  		name                string
   548  		header              http.Header
   549  		trailer             http.Header
   550  		valid               bool
   551  		maxHeaderBytes      int
   552  		maxHeaderValueCount int
   553  	}{{
   554  		name: "within limits",
   555  		header: {
   556  			"x-foo": {strings.Repeat("x", 1000)},
   557  		},
   558  		maxHeaderBytes: 1500,
   559  		valid:          true,
   560  	}, {
   561  		name: "too many header bytes",
   562  		header: {
   563  			"x-foo": {strings.Repeat("x", 1000)},
   564  			"x-bar": {strings.Repeat("x", 1000)},
   565  		},
   566  		maxHeaderBytes: 1500,
   567  	}, {
   568  		name: "sent trailer within limits",
   569  		header: {
   570  			"trailer": {"x-foo"},
   571  		},
   572  		trailer: http.Header{
   573  			"x-foo": {strings.Repeat("x", 1000)},
   574  		},
   575  		maxHeaderBytes: 1500,
   576  		valid:          true,
   577  	}, {
   578  		name: "too many sent trailer bytes",
   579  		header: {
   580  			"trailer": {"x-foo, x-bar"},
   581  		},
   582  		trailer: http.Header{
   583  			"x-foo": {strings.Repeat("x", 1000)},
   584  			"x-bar": {strings.Repeat("x", 1000)},
   585  		},
   586  		maxHeaderBytes: 1500,
   587  	}, {
   588  		name: "field count within limit",
   589  		header: {
   590  			// :method, :scheme, :path, plus:
   591  			"x-foo": {"4"},
   592  			"x-bar": {"5"},
   593  		},
   594  		maxHeaderBytes:      1500,
   595  		maxHeaderValueCount: 5,
   596  		valid:               true,
   597  	}, {
   598  		name: "field count over limit",
   599  		header: {
   600  			// :method, :scheme, :path, plus:
   601  			"x-foo": {"4"},
   602  			"x-bar": {"5"},
   603  		},
   604  		maxHeaderBytes:      1500,
   605  		maxHeaderValueCount: 4,
   606  	}, {
   607  		name: "declared trailer field count within limit",
   608  		header: {
   609  			"trailer": {"a, b, c, d, e"},
   610  		},
   611  		maxHeaderBytes:      1500,
   612  		maxHeaderValueCount: 5,
   613  		valid:               true,
   614  	}, {
   615  		name: "declared trailer field count over limit",
   616  		header: {
   617  			"trailer": {"a, b, c, d, e"},
   618  		},
   619  		maxHeaderBytes:      1500,
   620  		maxHeaderValueCount: 4,
   621  	}, {
   622  		name: "declared trailer bytes over limit",
   623  		header: {
   624  			"trailer": {strings.Repeat("a,", 50)},
   625  		},
   626  		maxHeaderBytes: 1500,
   627  	}} {
   628  		synctestSubtest(t, test.name, func(t *testing.T) {
   629  			ts := newTestServer(t, nil)
   630  			ts.s.srv1.MaxHeaderBytes = test.maxHeaderBytes
   631  			ts.s.srv1.MaxHeaderValueCount = test.maxHeaderValueCount
   632  			tc := ts.connect()
   633  			tc.greet()
   634  
   635  			reqStream := tc.newStream(streamTypeRequest)
   636  			reqStream.writeHeaders(requestHeader(test.header))
   637  
   638  			if test.trailer == nil && !test.valid {
   639  				reqStream.wantSomeHeaders(http.Header{
   640  					":status": {"431"},
   641  				})
   642  				reqStream.wantClosed("request is complete")
   643  				return
   644  			}
   645  
   646  			call := tc.nextHandlerCall()
   647  			if call == nil {
   648  				t.Fatal("no server handler call; want one")
   649  			}
   650  			if test.trailer == nil {
   651  				return
   652  			}
   653  
   654  			reqStream.writeHeaders(test.trailer)
   655  			_, err := io.ReadAll(call.req.Body)
   656  			if (err == nil) != test.valid {
   657  				t.Fatalf("io.ReadAll(req.Body) = %v, want valid=%v", err, test.valid)
   658  			}
   659  		})
   660  	}
   661  }
   662  
   663  func TestServerBody(t *testing.T) {
   664  	synctest.Test(t, func(t *testing.T) {
   665  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   666  			body, err := io.ReadAll(r.Body)
   667  			if err != nil {
   668  				t.Fatal(err)
   669  			}
   670  			w.Write([]byte(r.URL.Path)) // Implicitly calls w.WriteHeader(200).
   671  			w.Write(body)
   672  		}))
   673  		tc := ts.connect()
   674  		tc.greet()
   675  
   676  		reqStream := tc.newStream(streamTypeRequest)
   677  		reqStream.writeHeaders(requestHeader(nil))
   678  		bodyContent := []byte("some body content that should be echoed")
   679  		reqStream.writeData(bodyContent)
   680  		reqStream.CloseWrite()
   681  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
   682  		// Small multiple calls to Write will be coalesced into one DATA frame.
   683  		reqStream.wantData(append([]byte("/"), bodyContent...))
   684  		reqStream.wantClosed("request is complete")
   685  	})
   686  }
   687  
   688  func TestServerHeadResponseNoBody(t *testing.T) {
   689  	bodyContent := []byte("response body that will not be sent for HEAD requests")
   690  	synctest.Test(t, func(t *testing.T) {
   691  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   692  			w.Write(bodyContent)
   693  		}))
   694  		tc := ts.connect()
   695  		tc.greet()
   696  
   697  		reqStream := tc.newStream(streamTypeRequest)
   698  		reqStream.writeHeaders(requestHeader(nil))
   699  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
   700  		reqStream.wantData(bodyContent)
   701  		reqStream.wantClosed("request is complete")
   702  
   703  		reqStream = tc.newStream(streamTypeRequest)
   704  		reqStream.writeHeaders(requestHeader(http.Header{":method": {http.MethodHead}}))
   705  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
   706  		reqStream.wantClosed("request is complete")
   707  	})
   708  }
   709  
   710  func TestServerShutdownGoaway(t *testing.T) {
   711  	synctest.Test(t, func(t *testing.T) {
   712  		ts := newTestServer(t, nil)
   713  
   714  		tc := ts.connect()
   715  		tc.greet()
   716  		tc.wantNotClosed("after initial connection handshake")
   717  
   718  		requestCount := int64(5)
   719  		for range requestCount {
   720  			tc.newStream(streamTypeRequest).writeHeaders(requestHeader(nil))
   721  		}
   722  
   723  		control := tc.wantStream(streamTypeControl)
   724  		control.wantSettings(nil)
   725  
   726  		shutdownComplete := make(chan any)
   727  		go func() {
   728  			ts.s.shutdown(t.Context())
   729  			shutdownComplete <- struct{}{}
   730  		}()
   731  		control.wantGoaway((requestCount - 1) * 4) // Request stream ID goes from 0, 4, 8, ...
   732  		<-shutdownComplete
   733  	})
   734  }
   735  
   736  func TestServerHandlerEmpty(t *testing.T) {
   737  	synctest.Test(t, func(t *testing.T) {
   738  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   739  			// Empty handler should return a 200 OK
   740  		}))
   741  		tc := ts.connect()
   742  		tc.greet()
   743  
   744  		reqStream := tc.newStream(streamTypeRequest)
   745  		reqStream.writeHeaders(requestHeader(nil))
   746  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
   747  		reqStream.wantClosed("request is complete")
   748  	})
   749  }
   750  
   751  func TestServerHandlerFlushing(t *testing.T) {
   752  	synctest.Test(t, func(t *testing.T) {
   753  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   754  			time.Sleep(time.Second)
   755  			w.Write([]byte("first"))
   756  
   757  			time.Sleep(time.Second)
   758  			w.Write([]byte("second"))
   759  			w.(http.Flusher).Flush()
   760  
   761  			time.Sleep(time.Second)
   762  			w.Write([]byte("third"))
   763  		}))
   764  		tc := ts.connect()
   765  		tc.greet()
   766  
   767  		reqStream := tc.newStream(streamTypeRequest)
   768  		reqStream.writeHeaders(requestHeader(nil))
   769  		respBody := make([]byte, 100)
   770  
   771  		time.Sleep(time.Second)
   772  		synctest.Wait()
   773  		if n, err := reqStream.Read(respBody); err == nil {
   774  			t.Errorf("got %v bytes read, want no message yet", n)
   775  		}
   776  
   777  		time.Sleep(time.Second)
   778  		synctest.Wait()
   779  		if _, err := reqStream.Read(respBody); err != nil {
   780  			t.Errorf("failed to read partial response from server, got err: %v", err)
   781  		}
   782  
   783  		time.Sleep(time.Second)
   784  		synctest.Wait()
   785  		if _, err := reqStream.Read(respBody); err != io.EOF {
   786  			t.Errorf("got err %v, want EOF", err)
   787  		}
   788  		reqStream.wantClosed("request is complete")
   789  	})
   790  }
   791  
   792  func TestServerHandlerStreaming(t *testing.T) {
   793  	synctest.Test(t, func(t *testing.T) {
   794  		stream := make(chan string)
   795  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   796  			// Flushing when we have not written anything yet implicitly calls
   797  			// w.WriteHeader(200).
   798  			w.(http.Flusher).Flush()
   799  			for str := range stream {
   800  				w.Write([]byte(str))
   801  				w.(http.Flusher).Flush()
   802  			}
   803  		}))
   804  		tc := ts.connect()
   805  		tc.greet()
   806  
   807  		reqStream := tc.newStream(streamTypeRequest)
   808  		reqStream.writeHeaders(requestHeader(nil))
   809  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
   810  
   811  		for _, data := range []string{"a", "bunch", "of", "things", "to", "stream"} {
   812  			stream <- data
   813  			reqStream.wantData([]byte(data))
   814  		}
   815  		close(stream)
   816  		reqStream.wantClosed("request is complete")
   817  	})
   818  }
   819  
   820  func TestServerHandlerDeclaresContentLength(t *testing.T) {
   821  	tests := []struct {
   822  		name             string
   823  		contentLen       string
   824  		actualContentLen int
   825  		wantWrittenLen   int
   826  		wantTrimmed      bool
   827  		wantCLHeader     bool
   828  	}{
   829  		{
   830  			name:             "accurate content length",
   831  			contentLen:       "100",
   832  			actualContentLen: 100,
   833  			wantWrittenLen:   100,
   834  			wantCLHeader:     true,
   835  		},
   836  		{
   837  			name:             "larger content length",
   838  			contentLen:       "100",
   839  			actualContentLen: 10,
   840  			wantWrittenLen:   10,
   841  			wantCLHeader:     true,
   842  		},
   843  		{
   844  			name:             "smaller content length",
   845  			contentLen:       "10",
   846  			actualContentLen: 100,
   847  			wantWrittenLen:   10,
   848  			wantTrimmed:      true,
   849  			wantCLHeader:     true,
   850  		},
   851  		{
   852  			name:             "non-numeric string",
   853  			contentLen:       "intentional gibberish",
   854  			actualContentLen: 100,
   855  			wantWrittenLen:   100,
   856  		},
   857  		{
   858  			name:             "negative number",
   859  			contentLen:       "-10",
   860  			actualContentLen: 100,
   861  			wantWrittenLen:   100,
   862  		},
   863  		{
   864  			name:             "plus sign",
   865  			contentLen:       "+10",
   866  			actualContentLen: 100,
   867  			wantWrittenLen:   100,
   868  		},
   869  		{
   870  			name:             "empty",
   871  			contentLen:       "",
   872  			actualContentLen: 100,
   873  			wantWrittenLen:   100,
   874  		},
   875  		{
   876  			name:             "large valid content length",
   877  			contentLen:       "3000000000",
   878  			actualContentLen: 100,
   879  			wantWrittenLen:   100,
   880  			wantCLHeader:     true,
   881  		},
   882  		{
   883  			name:             "content length overflowing int64",
   884  			contentLen:       "9223372036854775808",
   885  			actualContentLen: 100,
   886  			wantWrittenLen:   100,
   887  		},
   888  	}
   889  
   890  	for _, tt := range tests {
   891  		synctestSubtest(t, tt.name, func(t *testing.T) {
   892  			ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   893  				w.Header().Set("Content-Length", tt.contentLen)
   894  				var written int
   895  				var lastErr error
   896  				for range tt.actualContentLen {
   897  					n, err := w.Write([]byte("a"))
   898  					written += n
   899  					lastErr = err
   900  				}
   901  				if tt.wantTrimmed != (lastErr != nil) {
   902  					t.Errorf("got %v error when writing response body, even though wantTrimmed is %v", lastErr, tt.wantTrimmed)
   903  				}
   904  				if written != tt.wantWrittenLen {
   905  					t.Errorf("got %v bytes written by the server, want %v bytes", written, tt.wantWrittenLen)
   906  				}
   907  			}))
   908  			tc := ts.connect()
   909  			tc.greet()
   910  
   911  			reqStream := tc.newStream(streamTypeRequest)
   912  			reqStream.writeHeaders(requestHeader(nil))
   913  			expectedHeaders := http.Header{
   914  				":status":      {"200"},
   915  				"Content-Type": {"text/plain; charset=utf-8"},
   916  				"Date":         {"Sat, 01 Jan 2000 00:00:00 GMT"}, // Synctest starting time.
   917  			}
   918  			if tt.wantCLHeader {
   919  				expectedHeaders.Set("Content-Length", tt.contentLen)
   920  			}
   921  			reqStream.wantHeaders(expectedHeaders)
   922  			reqStream.wantData(slices.Repeat([]byte("a"), tt.wantWrittenLen))
   923  			reqStream.wantClosed("request is complete")
   924  		})
   925  	}
   926  }
   927  
   928  func TestServerExpect100Continue(t *testing.T) {
   929  	synctest.Test(t, func(t *testing.T) {
   930  		streamIdle := make(chan bool)
   931  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   932  			// Expect: 100-continue header should not be accessible from the
   933  			// server handler.
   934  			if len(r.Header) > 0 {
   935  				t.Errorf("got %v, want request header to be empty", r.Header)
   936  			}
   937  			// Reading the body will cause the server to call w.WriteHeader(100).
   938  			<-streamIdle
   939  			body, err := io.ReadAll(r.Body)
   940  			if err != nil {
   941  				t.Fatal(err)
   942  			}
   943  			// Implicitly calls w.WriteHeader(200) since non-1XX status code
   944  			// has been sent yet so far.
   945  			w.Write(body)
   946  		}))
   947  		tc := ts.connect()
   948  		tc.greet()
   949  
   950  		// Client sends an Expect: 100-continue request.
   951  		reqStream := tc.newStream(streamTypeRequest)
   952  		reqStream.writeHeaders(requestHeader(http.Header{
   953  			"expect": {"100-continue"},
   954  		}))
   955  
   956  		reqStream.wantIdle("stream is idle until server sends an HTTP 100 status")
   957  		streamIdle <- true
   958  		// Wait until server responds with HTTP status 100 before sending the
   959  		// body.
   960  		reqStream.wantSomeHeaders(http.Header{":status": {"100"}})
   961  		body := []byte("body that will be echoed back if we get status 100")
   962  		reqStream.writeData(body)
   963  		reqStream.CloseWrite()
   964  
   965  		// Receive the server's response after sending the body.
   966  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
   967  		reqStream.wantData(body)
   968  		reqStream.wantClosed("request is complete")
   969  	})
   970  }
   971  
   972  func TestServerExpect100ContinueSentManually(t *testing.T) {
   973  	synctest.Test(t, func(t *testing.T) {
   974  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   975  			w.WriteHeader(100)
   976  			body, err := io.ReadAll(r.Body) // Should not send another 100.
   977  			if err != nil {
   978  				t.Fatal(err)
   979  			}
   980  			w.Write(body)
   981  		}))
   982  		tc := ts.connect()
   983  		tc.greet()
   984  
   985  		// Client sends an Expect: 100-continue request.
   986  		reqStream := tc.newStream(streamTypeRequest)
   987  		reqStream.writeHeaders(requestHeader(http.Header{
   988  			"expect": {"100-continue"},
   989  		}))
   990  
   991  		// Send the body once the server responds with HTTP status 100.
   992  		reqStream.wantSomeHeaders(http.Header{":status": {"100"}})
   993  		body := []byte("body that will be echoed back")
   994  		reqStream.writeData(body)
   995  		reqStream.CloseWrite()
   996  
   997  		// Verify that the server responds with 200, rather than another 100.
   998  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
   999  		reqStream.wantData(body)
  1000  		reqStream.wantClosed("request is complete")
  1001  	})
  1002  }
  1003  
  1004  func TestServerExpect100ContinueRejected(t *testing.T) {
  1005  	synctest.Test(t, func(t *testing.T) {
  1006  		rejectBody := []byte("not allowed")
  1007  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1008  			w.WriteHeader(403)
  1009  			w.Write(rejectBody)
  1010  		}))
  1011  		tc := ts.connect()
  1012  		tc.greet()
  1013  
  1014  		// Client sends an Expect: 100-continue request.
  1015  		reqStream := tc.newStream(streamTypeRequest)
  1016  		reqStream.writeHeaders(requestHeader(http.Header{
  1017  			"expect": {"100-continue"},
  1018  		}))
  1019  
  1020  		// Server rejects it.
  1021  		reqStream.wantSomeHeaders(http.Header{":status": {"403"}})
  1022  		reqStream.wantData(rejectBody)
  1023  		reqStream.wantClosed("request is complete")
  1024  	})
  1025  }
  1026  
  1027  func TestServer100ContinueBodyReadAfterFinalResponse(t *testing.T) {
  1028  	synctest.Test(t, func(t *testing.T) {
  1029  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1030  			w.WriteHeader(200)
  1031  			w.(http.Flusher).Flush()
  1032  			// Read should not cause an HTTP 100 status to be sent since we
  1033  			// have sent an HTTP 200 response already.
  1034  			// Read should also return an error and should not hang.
  1035  			if _, err := io.ReadAll(r.Body); err == nil {
  1036  				t.Errorf("got %v, want an error", err)
  1037  			}
  1038  		}))
  1039  		tc := ts.connect()
  1040  		tc.greet()
  1041  
  1042  		// Client sends an Expect: 100-continue request.
  1043  		reqStream := tc.newStream(streamTypeRequest)
  1044  		reqStream.writeHeaders(requestHeader(http.Header{
  1045  			"expect": {"100-continue"},
  1046  		}))
  1047  
  1048  		// Verify that no HTTP 100 was sent.
  1049  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
  1050  		reqStream.wantClosed("request is complete")
  1051  	})
  1052  }
  1053  
  1054  func TestServer100ContinueBodyReadAfter100AndFinalResponse(t *testing.T) {
  1055  	synctest.Test(t, func(t *testing.T) {
  1056  		body := []byte("client body")
  1057  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1058  			w.WriteHeader(100)
  1059  			w.WriteHeader(200)
  1060  			w.(http.Flusher).Flush()
  1061  			// Allow Read to succeed since the handler has sent 100 prior to 200.
  1062  			if gotBody, err := io.ReadAll(r.Body); err != nil || string(gotBody) != string(body) {
  1063  				t.Errorf("io.ReadAll(r.Body) = %v, %v; want %v, nil", gotBody, err, body)
  1064  			}
  1065  		}))
  1066  		tc := ts.connect()
  1067  		tc.greet()
  1068  
  1069  		// Client sends an Expect: 100-continue request.
  1070  		reqStream := tc.newStream(streamTypeRequest)
  1071  		reqStream.writeHeaders(requestHeader(http.Header{
  1072  			"expect": {"100-continue"},
  1073  		}))
  1074  
  1075  		// Send the body once the server responds with HTTP status 100.
  1076  		reqStream.wantSomeHeaders(http.Header{":status": {"100"}})
  1077  		reqStream.writeData(body)
  1078  		reqStream.CloseWrite()
  1079  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
  1080  		reqStream.wantClosed("request is complete")
  1081  	})
  1082  }
  1083  
  1084  func TestServerHandlerReadReqWithNoBody(t *testing.T) {
  1085  	synctest.Test(t, func(t *testing.T) {
  1086  		serverBody := []byte("hello from server!")
  1087  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1088  			if _, err := io.ReadAll(r.Body); err != nil {
  1089  				t.Errorf("got %v err when reading from an empty request body, want nil", err)
  1090  			}
  1091  			w.Write(serverBody)
  1092  		}))
  1093  		tc := ts.connect()
  1094  		tc.greet()
  1095  
  1096  		// Case 1: we know that there is no body / DATA frame because the
  1097  		// client closes the write direction of the stream.
  1098  		reqStream := tc.newStream(streamTypeRequest)
  1099  		reqStream.writeHeaders(requestHeader(nil))
  1100  		reqStream.CloseWrite()
  1101  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
  1102  		reqStream.wantData(serverBody)
  1103  		reqStream.wantClosed("request is complete")
  1104  
  1105  		// Case 2: we know that there is no body / DATA frame because the
  1106  		// client indicates a Content-Length of 0.
  1107  		reqStream = tc.newStream(streamTypeRequest)
  1108  		reqStream.writeHeaders(requestHeader(http.Header{
  1109  			"content-length": {"0"},
  1110  		}))
  1111  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
  1112  		reqStream.wantData(serverBody)
  1113  		reqStream.wantClosed("request is complete")
  1114  	})
  1115  }
  1116  
  1117  func TestServerHandlerReadTrailer(t *testing.T) {
  1118  	synctest.Test(t, func(t *testing.T) {
  1119  		body := []byte("some body")
  1120  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1121  			wantTrailer := http.Header{
  1122  				"Client-Trailer-A": nil,
  1123  				"Client-Trailer-B": nil,
  1124  			}
  1125  			if !reflect.DeepEqual(r.Trailer, wantTrailer) {
  1126  				t.Errorf("got %v; want trailer to be %v before reading the body", r.Trailer, wantTrailer)
  1127  			}
  1128  			if _, err := io.ReadAll(r.Body); err != nil {
  1129  				t.Fatal(err)
  1130  			}
  1131  			wantTrailer = http.Header{
  1132  				"Client-Trailer-A": {"valuea"},
  1133  				"Client-Trailer-B": {"valueb"},
  1134  			}
  1135  			if !reflect.DeepEqual(r.Trailer, wantTrailer) {
  1136  				t.Errorf("got %v; want trailer to be %v after reading the body", r.Trailer, wantTrailer)
  1137  			}
  1138  			w.WriteHeader(200)
  1139  		}))
  1140  		tc := ts.connect()
  1141  		tc.greet()
  1142  
  1143  		reqStream := tc.newStream(streamTypeRequest)
  1144  		reqStream.writeHeaders(requestHeader(http.Header{
  1145  			"trailer": {"Client-Trailer-A, Client-Trailer-B"},
  1146  		}))
  1147  		reqStream.writeData(body)
  1148  		reqStream.writeHeaders(http.Header{
  1149  			"Client-Trailer-A": {"valuea"},
  1150  			"Client-Trailer-B": {"valueb"},
  1151  			// Server should not accept undeclared trailers.
  1152  			"Undeclared-Trailer": {"undeclared"},
  1153  		})
  1154  		reqStream.wantHeaders(nil)
  1155  		reqStream.wantClosed("request is complete")
  1156  	})
  1157  }
  1158  
  1159  func TestServerHandlerReadTrailerNoBody(t *testing.T) {
  1160  	synctest.Test(t, func(t *testing.T) {
  1161  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1162  			wantTrailer := http.Header{
  1163  				"Client-Trailer-A": nil,
  1164  				"Client-Trailer-B": nil,
  1165  			}
  1166  			if !reflect.DeepEqual(r.Trailer, wantTrailer) {
  1167  				t.Errorf("got %v; want trailer to be %v before reading the body", r.Trailer, wantTrailer)
  1168  			}
  1169  			if _, err := io.ReadAll(r.Body); err != nil {
  1170  				t.Fatal(err)
  1171  			}
  1172  			wantTrailer = http.Header{
  1173  				"Client-Trailer-A": {"valuea"},
  1174  				"Client-Trailer-B": {"valueb"},
  1175  			}
  1176  			if !reflect.DeepEqual(r.Trailer, wantTrailer) {
  1177  				t.Errorf("got %v; want trailer to be %v after reading the body", r.Trailer, wantTrailer)
  1178  			}
  1179  			w.WriteHeader(200)
  1180  		}))
  1181  		tc := ts.connect()
  1182  		tc.greet()
  1183  
  1184  		reqStream := tc.newStream(streamTypeRequest)
  1185  		reqStream.writeHeaders(requestHeader(http.Header{
  1186  			"trailer":        {"Client-Trailer-A, Client-Trailer-B"},
  1187  			"content-length": {"0"},
  1188  		}))
  1189  		reqStream.writeHeaders(http.Header{
  1190  			"Client-Trailer-A": {"valuea"},
  1191  			"Client-Trailer-B": {"valueb"},
  1192  			// Server should not accept undeclared trailers.
  1193  			"Undeclared-Trailer": {"undeclared"},
  1194  		})
  1195  		reqStream.wantHeaders(nil)
  1196  		reqStream.wantClosed("request is complete")
  1197  	})
  1198  }
  1199  
  1200  func TestServerHandlerWriteTrailer(t *testing.T) {
  1201  	synctest.Test(t, func(t *testing.T) {
  1202  		body := []byte("some body")
  1203  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1204  			w.Header().Set("Trailer", "server-trailer-a, server-trailer-b") // Trailer header will be canonicalized.
  1205  			w.Header().Add("Trailer", "Server-Trailer-C")
  1206  
  1207  			w.Write(body)
  1208  
  1209  			w.Header().Set("server-trailer-a", "valuea") // Trailer header will be canonicalized.
  1210  			w.Header().Set("Server-Trailer-C", "valuec") // skipping B
  1211  			// Server should not send undeclared trailers, unless it has the
  1212  			// magic "Trailer:" prefix.
  1213  			w.Header().Set("Server-Trailer-Not-Declared", "should be omitted")
  1214  			w.Header().Set("Trailer:Undeclared-Trailer-Exception", "should be sent")
  1215  		}))
  1216  		tc := ts.connect()
  1217  		tc.greet()
  1218  
  1219  		reqStream := tc.newStream(streamTypeRequest)
  1220  		reqStream.writeHeaders(requestHeader(nil))
  1221  		reqStream.wantSomeHeaders(http.Header{
  1222  			":status": {"200"},
  1223  			"Trailer": {"Server-Trailer-A, Server-Trailer-B, Server-Trailer-C"},
  1224  		})
  1225  		reqStream.wantData(body)
  1226  		reqStream.wantSomeHeaders(http.Header{
  1227  			"Server-Trailer-A":             {"valuea"},
  1228  			"Server-Trailer-C":             {"valuec"},
  1229  			"Undeclared-Trailer-Exception": {"should be sent"},
  1230  		})
  1231  		reqStream.wantClosed("request is complete")
  1232  	})
  1233  }
  1234  
  1235  func TestServerHandlerWriteTrailerNoBody(t *testing.T) {
  1236  	synctest.Test(t, func(t *testing.T) {
  1237  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1238  			w.Header().Set("Trailer", "server-trailer-a, server-trailer-b") // Trailer header will be canonicalized.
  1239  			w.Header().Add("Trailer", "Server-Trailer-C")
  1240  
  1241  			w.(http.Flusher).Flush()
  1242  
  1243  			w.Header().Set("server-trailer-a", "valuea") // Trailer header will be canonicalized.
  1244  			w.Header().Set("Server-Trailer-C", "valuec") // skipping B
  1245  			// Server should not send undeclared trailers without "Trailer:"
  1246  			// prefix.
  1247  			w.Header().Set("Server-Trailer-Not-Declared", "should be omitted")
  1248  			w.Header().Set("Trailer:undeclared-trailer-exception", "should be sent")
  1249  		}))
  1250  		tc := ts.connect()
  1251  		tc.greet()
  1252  
  1253  		reqStream := tc.newStream(streamTypeRequest)
  1254  		reqStream.writeHeaders(requestHeader(nil))
  1255  		reqStream.wantSomeHeaders(http.Header{
  1256  			":status": {"200"},
  1257  			"Trailer": {"Server-Trailer-A, Server-Trailer-B, Server-Trailer-C"},
  1258  		})
  1259  		reqStream.wantSomeHeaders(http.Header{
  1260  			"Server-Trailer-A":             {"valuea"},
  1261  			"Server-Trailer-C":             {"valuec"},
  1262  			"Undeclared-Trailer-Exception": {"should be sent"},
  1263  		})
  1264  		reqStream.wantClosed("request is complete")
  1265  	})
  1266  }
  1267  
  1268  func TestServerInfersHeaders(t *testing.T) {
  1269  	tests := []struct {
  1270  		name            string
  1271  		flushedEarly    bool
  1272  		responseStatus  int
  1273  		does100Continue bool
  1274  		declaredHeader  http.Header
  1275  		want            http.Header
  1276  	}{
  1277  		{
  1278  			name:           "infers undeclared headers",
  1279  			responseStatus: 200,
  1280  			declaredHeader: http.Header{
  1281  				"Some-Other-Header": {"some value"},
  1282  			},
  1283  			want: http.Header{
  1284  				"Date":              {"Sat, 01 Jan 2000 00:00:00 GMT"}, // Synctest starting time.
  1285  				"Content-Type":      {"text/html; charset=utf-8"},
  1286  				"Some-Other-Header": {"some value"},
  1287  			},
  1288  		},
  1289  		{
  1290  			name:           "does not write over declared header",
  1291  			responseStatus: 200,
  1292  			declaredHeader: http.Header{
  1293  				"Date":              {"some date"},
  1294  				"Content-Type":      {"some content type"},
  1295  				"Some-Other-Header": {"some value"},
  1296  			},
  1297  			want: http.Header{
  1298  				"Date":              {"some date"},
  1299  				"Content-Type":      {"some content type"},
  1300  				"Some-Other-Header": {"some value"},
  1301  			},
  1302  		},
  1303  		{
  1304  			name:           "does not infer content type for response with no body",
  1305  			responseStatus: 304, // 304 status response has no body.
  1306  			declaredHeader: http.Header{
  1307  				"Some-Other-Header": {"some value"},
  1308  			},
  1309  			want: http.Header{
  1310  				"Date":              {"Sat, 01 Jan 2000 00:00:00 GMT"}, // Synctest starting time.
  1311  				"Some-Other-Header": {"some value"},
  1312  			},
  1313  		},
  1314  		{
  1315  			// See golang.org/issue/31753.
  1316  			name:           "does not infer content type for response with declared content encoding",
  1317  			responseStatus: 200,
  1318  			declaredHeader: http.Header{
  1319  				"Content-Encoding":  {"some encoding"},
  1320  				"Some-Other-Header": {"some value"},
  1321  			},
  1322  			want: http.Header{
  1323  				"Date":              {"Sat, 01 Jan 2000 00:00:00 GMT"}, // Synctest starting time.
  1324  				"Content-Encoding":  {"some encoding"},
  1325  				"Some-Other-Header": {"some value"},
  1326  			},
  1327  		},
  1328  		{
  1329  			name:           "infers content type for response with empty content encoding",
  1330  			responseStatus: 200,
  1331  			declaredHeader: http.Header{
  1332  				"Content-Encoding":  {""},
  1333  				"Some-Other-Header": {"some value"},
  1334  			},
  1335  			want: http.Header{
  1336  				"Date":              {"Sat, 01 Jan 2000 00:00:00 GMT"}, // Synctest starting time.
  1337  				"Content-Encoding":  {""},
  1338  				"Content-Type":      {"text/html; charset=utf-8"},
  1339  				"Some-Other-Header": {"some value"},
  1340  			},
  1341  		},
  1342  		{
  1343  			name:           "does not infer content type when header is flushed before body is written",
  1344  			responseStatus: 200,
  1345  			flushedEarly:   true,
  1346  			declaredHeader: http.Header{
  1347  				"Some-Other-Header": {"some value"},
  1348  			},
  1349  			want: http.Header{
  1350  				"Date":              {"Sat, 01 Jan 2000 00:00:00 GMT"}, // Synctest starting time.
  1351  				"Some-Other-Header": {"some value"},
  1352  			},
  1353  		},
  1354  		{
  1355  			name:            "infers header for the header that comes after 100 continue",
  1356  			responseStatus:  200,
  1357  			does100Continue: true,
  1358  			declaredHeader: http.Header{
  1359  				"Some-Other-Header": {"some value"},
  1360  			},
  1361  			want: http.Header{
  1362  				"Date":              {"Sat, 01 Jan 2000 00:00:00 GMT"}, // Synctest starting time.
  1363  				"Content-Type":      {"text/html; charset=utf-8"},
  1364  				"Some-Other-Header": {"some value"},
  1365  			},
  1366  		},
  1367  	}
  1368  
  1369  	for _, tt := range tests {
  1370  		synctestSubtest(t, tt.name, func(t *testing.T) {
  1371  			body := []byte("<html>some html content</html>")
  1372  			streamIdle := make(chan bool)
  1373  			ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1374  				if tt.does100Continue {
  1375  					<-streamIdle
  1376  					io.ReadAll(r.Body)
  1377  				}
  1378  				for name, values := range tt.declaredHeader {
  1379  					for _, value := range values {
  1380  						w.Header().Add(name, value)
  1381  					}
  1382  				}
  1383  				w.WriteHeader(tt.responseStatus)
  1384  				if tt.flushedEarly {
  1385  					w.(http.Flusher).Flush()
  1386  				}
  1387  				// Write the body one byte at a time. To confirm that body
  1388  				// writes are buffered and that Content-Type will not be
  1389  				// wrongly identified as text/plain rather than text/html.
  1390  				for _, b := range body {
  1391  					w.Write([]byte{b})
  1392  				}
  1393  			}))
  1394  			tc := ts.connect()
  1395  			tc.greet()
  1396  
  1397  			reqStream := tc.newStream(streamTypeRequest)
  1398  
  1399  			if tt.does100Continue {
  1400  				reqStream.writeHeaders(requestHeader(http.Header{
  1401  					"expect": {"100-continue"},
  1402  				}))
  1403  				reqStream.wantIdle("stream is idle until server sends an HTTP 100 status")
  1404  				streamIdle <- true
  1405  				reqStream.wantHeaders(http.Header{":status": {"100"}})
  1406  			}
  1407  
  1408  			reqStream.writeHeaders(requestHeader(nil))
  1409  			tt.want.Add(":status", strconv.Itoa(tt.responseStatus))
  1410  			reqStream.wantHeaders(tt.want)
  1411  			if responseCanHaveBody(tt.responseStatus) {
  1412  				reqStream.wantData(body)
  1413  			}
  1414  			reqStream.wantClosed("request is complete")
  1415  		})
  1416  	}
  1417  }
  1418  
  1419  func TestServerBuffersBodyWrite(t *testing.T) {
  1420  	tests := []struct {
  1421  		name      string
  1422  		bodyLen   int
  1423  		writeSize int
  1424  		flushes   bool
  1425  	}{
  1426  		{
  1427  			name:      "buffers small body content",
  1428  			bodyLen:   defaultBodyBufferCap * 10,
  1429  			writeSize: 5,
  1430  			flushes:   false,
  1431  		},
  1432  		{
  1433  			name:      "does not buffer large body content",
  1434  			bodyLen:   defaultBodyBufferCap * 10,
  1435  			writeSize: defaultBodyBufferCap * 2,
  1436  			flushes:   false,
  1437  		},
  1438  		{
  1439  			name:      "does not buffer flushed body content",
  1440  			bodyLen:   defaultBodyBufferCap * 10,
  1441  			writeSize: 10,
  1442  			flushes:   true,
  1443  		},
  1444  	}
  1445  	for _, tt := range tests {
  1446  		synctestSubtest(t, tt.name, func(t *testing.T) {
  1447  			ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1448  				for n := 0; n < tt.bodyLen; n += tt.writeSize {
  1449  					data := slices.Repeat([]byte("a"), min(tt.writeSize, tt.bodyLen-n))
  1450  					n, err := w.Write(data)
  1451  					if err != nil {
  1452  						t.Fatal(err)
  1453  					}
  1454  					if n != len(data) {
  1455  						t.Errorf("got %v bytes when writing in server handler, want %v", n, len(data))
  1456  					}
  1457  					if tt.flushes {
  1458  						w.(http.Flusher).Flush()
  1459  					}
  1460  				}
  1461  			}))
  1462  			tc := ts.connect()
  1463  			tc.greet()
  1464  
  1465  			reqStream := tc.newStream(streamTypeRequest)
  1466  			reqStream.writeHeaders(requestHeader(nil))
  1467  			reqStream.wantHeaders(nil)
  1468  			switch {
  1469  			case tt.writeSize > defaultBodyBufferCap:
  1470  				// After using the buffer once, it is no longer used since the
  1471  				// writeSize is larger than the buffer.
  1472  				for n := 0; n < tt.bodyLen; n += tt.writeSize {
  1473  					reqStream.wantData(slices.Repeat([]byte("a"), min(tt.writeSize, tt.bodyLen-n)))
  1474  				}
  1475  			case tt.flushes:
  1476  				for n := 0; n < tt.bodyLen; n += tt.writeSize {
  1477  					reqStream.wantData(slices.Repeat([]byte("a"), min(tt.writeSize, tt.bodyLen-n)))
  1478  				}
  1479  			case tt.writeSize <= defaultBodyBufferCap:
  1480  				dataLen := defaultBodyBufferCap + tt.writeSize - (defaultBodyBufferCap % tt.writeSize)
  1481  				for n := 0; n < tt.bodyLen; n += dataLen {
  1482  					reqStream.wantData(slices.Repeat([]byte("a"), min(dataLen, tt.bodyLen-n)))
  1483  				}
  1484  			}
  1485  			reqStream.wantClosed("request is complete")
  1486  		})
  1487  	}
  1488  }
  1489  
  1490  func TestServer103EarlyHints(t *testing.T) {
  1491  	synctest.Test(t, func(t *testing.T) {
  1492  		body := []byte("some body")
  1493  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1494  			h := w.Header()
  1495  
  1496  			h.Add("Content-Length", "123") // Must be ignored
  1497  			h.Add("Link", "</style.css>; rel=preload; as=style")
  1498  			h.Add("Link", "</script.js>; rel=preload; as=script")
  1499  			w.WriteHeader(http.StatusEarlyHints)
  1500  
  1501  			h.Add("Link", "</foo.js>; rel=preload; as=script")
  1502  			w.WriteHeader(http.StatusEarlyHints)
  1503  
  1504  			w.Write(body)                        // Implicitly sends status 200.
  1505  			w.WriteHeader(http.StatusEarlyHints) // Should be a no-op.
  1506  		}))
  1507  		tc := ts.connect()
  1508  		tc.greet()
  1509  
  1510  		reqStream := tc.newStream(streamTypeRequest)
  1511  		reqStream.writeHeaders(requestHeader(nil))
  1512  		reqStream.wantHeaders(http.Header{
  1513  			":status": {"103"},
  1514  			"Link": {
  1515  				"</style.css>; rel=preload; as=style",
  1516  				"</script.js>; rel=preload; as=script",
  1517  			},
  1518  		})
  1519  		reqStream.wantHeaders(http.Header{
  1520  			":status": {"103"},
  1521  			"Link": {
  1522  				"</style.css>; rel=preload; as=style",
  1523  				"</script.js>; rel=preload; as=script",
  1524  				"</foo.js>; rel=preload; as=script",
  1525  			},
  1526  		})
  1527  		reqStream.wantSomeHeaders(http.Header{
  1528  			":status":        {"200"},
  1529  			"Content-Length": {"123"},
  1530  		})
  1531  		reqStream.wantData(body)
  1532  		reqStream.wantClosed("request is complete")
  1533  	})
  1534  }
  1535  
  1536  func TestServer304NotModified(t *testing.T) {
  1537  	synctest.Test(t, func(t *testing.T) {
  1538  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1539  			w.WriteHeader(http.StatusNotModified)
  1540  			if _, err := w.Write([]byte("body should not be allowed")); !errors.Is(err, http.ErrBodyNotAllowed) {
  1541  				t.Errorf("got %v error when calling Write after WriteHeader(304), want %v error", err, http.ErrBodyNotAllowed)
  1542  			}
  1543  		}))
  1544  		tc := ts.connect()
  1545  		tc.greet()
  1546  
  1547  		reqStream := tc.newStream(streamTypeRequest)
  1548  		reqStream.writeHeaders(requestHeader(nil))
  1549  		reqStream.wantSomeHeaders(http.Header{":status": {"304"}})
  1550  		reqStream.wantClosed("request is complete")
  1551  	})
  1552  }
  1553  
  1554  func TestServerInvalidPathHeader(t *testing.T) {
  1555  	for _, test := range []struct {
  1556  		name string
  1557  		path string
  1558  	}{{
  1559  		name: "empty",
  1560  		path: "",
  1561  	}, {
  1562  		name: "invalid char",
  1563  		path: "\x00",
  1564  	}, {
  1565  		name: "absolute url",
  1566  		path: "https://example.com/",
  1567  	}} {
  1568  		synctestSubtest(t, test.name, func(t *testing.T) {
  1569  			ts := newTestServer(t, nil)
  1570  			tc := ts.connect()
  1571  			tc.greet()
  1572  
  1573  			reqStream := tc.newStream(streamTypeRequest)
  1574  			reqStream.writeHeaders(requestHeader(http.Header{
  1575  				":path": []string{test.path},
  1576  			}))
  1577  			reqStream.wantError(quic.StreamError(errH3MessageError))
  1578  		})
  1579  	}
  1580  }
  1581  
  1582  func TestServerOptionsMethod(t *testing.T) {
  1583  	synctest.Test(t, func(t *testing.T) {
  1584  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
  1585  		tc := ts.connect()
  1586  		tc.greet()
  1587  
  1588  		reqStream := tc.newStream(streamTypeRequest)
  1589  		reqStream.writeHeaders(requestHeader(http.Header{
  1590  			":method": []string{"OPTIONS"},
  1591  			":path":   []string{"*"},
  1592  		}))
  1593  		reqStream.wantSomeHeaders(http.Header{
  1594  			":status": {"200"},
  1595  		})
  1596  	})
  1597  }
  1598  
  1599  func TestServerPastWriteDeadline(t *testing.T) {
  1600  	synctest.Test(t, func(t *testing.T) {
  1601  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1602  			ctl := http.NewResponseController(w)
  1603  			io.WriteString(w, "one")
  1604  			if err := ctl.Flush(); err != nil {
  1605  				t.Errorf("Flush() = %v, want nil", err)
  1606  			}
  1607  			time.Sleep(time.Second) // T+1.
  1608  			// Set past write deadline. Write should fail.
  1609  			if err := ctl.SetWriteDeadline(time.Now().Add(-10 * time.Second)); err != nil {
  1610  				t.Errorf("SetWriteDeadline() = %v, want nil", err)
  1611  			}
  1612  			var err error
  1613  			_, err = io.WriteString(w, "x")
  1614  			if err == nil {
  1615  				err = ctl.Flush()
  1616  			}
  1617  			if !errors.Is(err, os.ErrDeadlineExceeded) {
  1618  				t.Errorf("got write err %v, want %v", err, os.ErrDeadlineExceeded)
  1619  			}
  1620  
  1621  			// Extending the write deadline after it's exceeded should have no effect (sticky).
  1622  			if err := ctl.SetWriteDeadline(time.Now().Add(10 * time.Second)); err != nil {
  1623  				t.Errorf("SetWriteDeadline() = %v, want nil", err)
  1624  			}
  1625  			_, err = io.WriteString(w, "x")
  1626  			if err == nil {
  1627  				err = ctl.Flush()
  1628  			}
  1629  			if !errors.Is(err, os.ErrDeadlineExceeded) {
  1630  				t.Errorf("got write err %v (after extend), want %v", err, os.ErrDeadlineExceeded)
  1631  			}
  1632  		}))
  1633  		tc := ts.connect()
  1634  		tc.greet()
  1635  
  1636  		reqStream := tc.newStream(streamTypeRequest)
  1637  		reqStream.writeHeaders(requestHeader(nil))
  1638  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
  1639  		reqStream.wantData([]byte("one"))
  1640  		time.Sleep(2 * time.Second) // T+2.
  1641  		synctest.Wait()
  1642  		reqStream.wantError(quic.StreamError(errH3RequestCancelled))
  1643  	})
  1644  }
  1645  
  1646  func TestServerFutureWriteDeadline(t *testing.T) {
  1647  	synctest.Test(t, func(t *testing.T) {
  1648  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1649  			ctl := http.NewResponseController(w)
  1650  			io.WriteString(w, "one")
  1651  			if err := ctl.Flush(); err != nil {
  1652  				t.Errorf("Flush() = %v, want nil", err)
  1653  			}
  1654  
  1655  			// Set future deadline at T+1. Write should succeed.
  1656  			if err := ctl.SetWriteDeadline(time.Now().Add(time.Second)); err != nil {
  1657  				t.Errorf("SetWriteDeadline() = %v, want nil", err)
  1658  			}
  1659  			io.WriteString(w, "two")
  1660  			if err := ctl.Flush(); err != nil {
  1661  				t.Errorf("Flush() = %v, want nil", err)
  1662  			}
  1663  
  1664  			// Extend deadline to T+3, before it expires.
  1665  			if err := ctl.SetWriteDeadline(time.Now().Add(3 * time.Second)); err != nil {
  1666  				t.Errorf("SetWriteDeadline() = %v, want nil", err)
  1667  			}
  1668  			// Sleep till T+2. Write should succeed since the deadline is T+3.
  1669  			time.Sleep(2 * time.Second)
  1670  			io.WriteString(w, "three")
  1671  			if err := ctl.Flush(); err != nil {
  1672  				t.Errorf("Flush() = %v, want nil", err)
  1673  			}
  1674  
  1675  			// Sleep till T+4. Write should fail since deadline is T+3.
  1676  			time.Sleep(2 * time.Second)
  1677  			var err error
  1678  			_, err = io.WriteString(w, "x")
  1679  			if err == nil {
  1680  				err = ctl.Flush()
  1681  			}
  1682  			if !errors.Is(err, os.ErrDeadlineExceeded) {
  1683  				t.Errorf("got write err %v, want %v", err, os.ErrDeadlineExceeded)
  1684  			}
  1685  
  1686  			// Extending the write deadline after it's exceeded should have no effect (sticky).
  1687  			if err := ctl.SetWriteDeadline(time.Time{}); err != nil {
  1688  				t.Errorf("SetWriteDeadline() = %v, want nil", err)
  1689  			}
  1690  			_, err = io.WriteString(w, "x")
  1691  			if err == nil {
  1692  				err = ctl.Flush()
  1693  			}
  1694  			if !errors.Is(err, os.ErrDeadlineExceeded) {
  1695  				t.Errorf("got write err %v (after extend), want %v", err, os.ErrDeadlineExceeded)
  1696  			}
  1697  		}))
  1698  		tc := ts.connect()
  1699  		tc.greet()
  1700  
  1701  		reqStream := tc.newStream(streamTypeRequest)
  1702  		reqStream.writeHeaders(requestHeader(nil))
  1703  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
  1704  		reqStream.wantData([]byte("one"))
  1705  		reqStream.wantData([]byte("two"))
  1706  		time.Sleep(3 * time.Second) // T+3. After "three" is written.
  1707  		reqStream.wantData([]byte("three"))
  1708  		time.Sleep(3 * time.Second) // T+6. After server exceeds deadline.
  1709  		reqStream.wantError(quic.StreamError(errH3RequestCancelled))
  1710  	})
  1711  }
  1712  
  1713  func TestServerPastReadDeadline(t *testing.T) {
  1714  	synctest.Test(t, func(t *testing.T) {
  1715  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1716  			ctl := http.NewResponseController(w)
  1717  			b := make([]byte, 3)
  1718  			if _, err := io.ReadFull(r.Body, b); err != nil || string(b) != "one" {
  1719  				t.Errorf("Read() got (%q, %v), want (%q, nil)", b, err, "one")
  1720  			}
  1721  			// Set past read deadline. Read should fail.
  1722  			if err := ctl.SetReadDeadline(time.Now().Add(-10 * time.Second)); err != nil {
  1723  				t.Errorf("SetReadDeadline() = %v, want nil", err)
  1724  			}
  1725  			_, err := io.ReadAll(r.Body)
  1726  			if !errors.Is(err, os.ErrDeadlineExceeded) {
  1727  				t.Errorf("got read err %v, want %v", err, os.ErrDeadlineExceeded)
  1728  			}
  1729  
  1730  			// Extending the read deadline after it's exceeded should have no effect (sticky).
  1731  			if err := ctl.SetReadDeadline(time.Now().Add(10 * time.Second)); err != nil {
  1732  				t.Errorf("SetReadDeadline() = %v, want nil", err)
  1733  			}
  1734  			_, err = io.ReadAll(r.Body)
  1735  			if !errors.Is(err, os.ErrDeadlineExceeded) {
  1736  				t.Errorf("got read err %v (after extend), want %v", err, os.ErrDeadlineExceeded)
  1737  			}
  1738  		}))
  1739  		tc := ts.connect()
  1740  		tc.greet()
  1741  
  1742  		reqStream := tc.newStream(streamTypeRequest)
  1743  		reqStream.writeHeaders(requestHeader(nil))
  1744  		reqStream.writeData([]byte("one"))
  1745  		synctest.Wait()
  1746  	})
  1747  }
  1748  
  1749  func TestServerFutureReadDeadline(t *testing.T) {
  1750  	synctest.Test(t, func(t *testing.T) {
  1751  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1752  			ctl := http.NewResponseController(w)
  1753  			b := make([]byte, 3)
  1754  			if _, err := io.ReadFull(r.Body, b); err != nil || string(b) != "one" {
  1755  				t.Errorf("Read() got (%q, %v), want (%q, nil)", b, err, "one")
  1756  			}
  1757  
  1758  			// Set future deadline at T+2s. Read should succeed.
  1759  			if err := ctl.SetReadDeadline(time.Now().Add(2 * time.Second)); err != nil {
  1760  				t.Errorf("SetReadDeadline() = %v, want nil", err)
  1761  			}
  1762  			b2 := make([]byte, 3)
  1763  			if _, err := io.ReadFull(r.Body, b2); err != nil || string(b2) != "two" {
  1764  				t.Errorf("Read() got (%q, %v), want (%q, nil)", b2, err, "two")
  1765  			}
  1766  
  1767  			// Extend deadline to T+5s, before it expires.
  1768  			if err := ctl.SetReadDeadline(time.Now().Add(4 * time.Second)); err != nil {
  1769  				t.Errorf("SetReadDeadline() = %v, want nil", err)
  1770  			}
  1771  			// Sleep till T+3. Read should succeed since the deadline is T+5.
  1772  			time.Sleep(2 * time.Second)
  1773  			b3 := make([]byte, 5)
  1774  			if _, err := io.ReadFull(r.Body, b3); err != nil || string(b3) != "three" {
  1775  				t.Errorf("Read() got (%q, %v), want (%q, nil)", b3, err, "three")
  1776  			}
  1777  
  1778  			// Sleep till T+6. Read should fail since deadline has passed.
  1779  			time.Sleep(3 * time.Second)
  1780  			_, err := io.ReadAll(r.Body)
  1781  			if !errors.Is(err, os.ErrDeadlineExceeded) {
  1782  				t.Errorf("got read err %v, want %v", err, os.ErrDeadlineExceeded)
  1783  			}
  1784  
  1785  			// Extending the read deadline after it's exceeded should have no effect (sticky).
  1786  			if err := ctl.SetReadDeadline(time.Time{}); err != nil {
  1787  				t.Errorf("SetReadDeadline() = %v, want nil", err)
  1788  			}
  1789  			_, err = io.ReadAll(r.Body)
  1790  			if !errors.Is(err, os.ErrDeadlineExceeded) {
  1791  				t.Errorf("got read err %v (after extend), want %v", err, os.ErrDeadlineExceeded)
  1792  			}
  1793  		}))
  1794  		tc := ts.connect()
  1795  		tc.greet()
  1796  
  1797  		reqStream := tc.newStream(streamTypeRequest)
  1798  		reqStream.writeHeaders(requestHeader(nil))
  1799  		reqStream.writeData([]byte("one"))
  1800  
  1801  		time.Sleep(time.Second)
  1802  		reqStream.writeData([]byte("two")) // T+1.
  1803  		synctest.Wait()
  1804  
  1805  		time.Sleep(time.Second)
  1806  		reqStream.writeData([]byte("three")) // T+2.
  1807  		synctest.Wait()
  1808  
  1809  		time.Sleep(4 * time.Second) // Advance to T+6 for server handler to complete.
  1810  	})
  1811  }
  1812  
  1813  func TestServerReadHeaderTimeout(t *testing.T) {
  1814  	synctest.Test(t, func(t *testing.T) {
  1815  		timeout := 10 * time.Second
  1816  		ts := newTestServer(t, nil)
  1817  		ts.s.srv1.ReadHeaderTimeout = timeout
  1818  		tc := ts.connect()
  1819  		tc.greet()
  1820  
  1821  		// Write some part of the header, but never finish sending it.
  1822  		reqStream := tc.newStream(streamTypeRequest)
  1823  		reqStream.writeVarint(int64(frameTypeHeaders))
  1824  		if err := reqStream.Flush(); err != nil {
  1825  			t.Fatalf("Flush() = %v, want nil", err)
  1826  		}
  1827  
  1828  		// A stream error should be sent to the client as soon as the timeout
  1829  		// is reached. Server handler should not be called.
  1830  		time.Sleep(timeout - 1)
  1831  		reqStream.wantIdle("timeout has not been reached")
  1832  		time.Sleep(1)
  1833  		reqStream.wantError(quic.StreamError(errH3RequestRejected))
  1834  		if tc.nextHandlerCall() != nil {
  1835  			t.Error("server handler should not be called")
  1836  		}
  1837  	})
  1838  }
  1839  
  1840  func TestServerReadTimeout(t *testing.T) {
  1841  	synctest.Test(t, func(t *testing.T) {
  1842  		timeout := 10 * time.Second
  1843  		ts := newTestServer(t, nil)
  1844  		ts.s.srv1.ReadTimeout = timeout
  1845  		tc := ts.connect()
  1846  		tc.greet()
  1847  
  1848  		reqStream := tc.newStream(streamTypeRequest)
  1849  		reqStream.writeHeaders(requestHeader(nil))
  1850  		reqStream.writeData([]byte("some body"))
  1851  		call := tc.nextHandlerCall()
  1852  
  1853  		// Read within the server handler should succeed prior to timeout.
  1854  		time.Sleep(timeout - 1)
  1855  		synctest.Wait()
  1856  		if _, err := call.req.Body.Read(make([]byte, 1)); err != nil {
  1857  			t.Errorf("Read() before timeout = %v, want nil", err)
  1858  		}
  1859  
  1860  		// Read within the server handler should fail once timeout is reached.
  1861  		// Stream error should not be sent to the client, as it is up to the
  1862  		// server handler to decide how it wants to deal with its inability to
  1863  		// read the request body.
  1864  		time.Sleep(1)
  1865  		synctest.Wait()
  1866  		if _, err := call.req.Body.Read(make([]byte, 1)); !errors.Is(err, os.ErrDeadlineExceeded) {
  1867  			t.Errorf("Read() after timeout = %v, want os.ErrDeadlineExceeded", err)
  1868  		}
  1869  		call.w.Write([]byte("some body"))
  1870  		call.exit()
  1871  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
  1872  		reqStream.wantData([]byte("some body"))
  1873  		reqStream.wantClosed("clean close expected")
  1874  	})
  1875  }
  1876  
  1877  func TestServerReadTimeoutInProgress(t *testing.T) {
  1878  	synctest.Test(t, func(t *testing.T) {
  1879  		timeout := 10 * time.Second
  1880  		ts := newTestServer(t, nil)
  1881  		ts.s.srv1.ReadTimeout = timeout
  1882  		tc := ts.connect()
  1883  		tc.greet()
  1884  
  1885  		reqStream := tc.newStream(streamTypeRequest)
  1886  		reqStream.writeHeaders(requestHeader(nil))
  1887  		reqStream.Flush()
  1888  		call := tc.nextHandlerCall()
  1889  
  1890  		// Read will block due to the client having sent no body, thus
  1891  		// advancing synctest's time.
  1892  		start := time.Now()
  1893  		_, err := call.req.Body.Read(make([]byte, 1))
  1894  		if !errors.Is(err, os.ErrDeadlineExceeded) {
  1895  			t.Errorf("Read error = %v, want os.ErrDeadlineExceeded", err)
  1896  		}
  1897  		if got, want := time.Since(start), timeout; got != want {
  1898  			t.Errorf("Read blocked for %v, want %v", got, want)
  1899  		}
  1900  		call.exit()
  1901  	})
  1902  }
  1903  
  1904  func TestServerWriteTimeout(t *testing.T) {
  1905  	synctest.Test(t, func(t *testing.T) {
  1906  		timeout := 10 * time.Second
  1907  		ts := newTestServer(t, nil)
  1908  		ts.s.srv1.WriteTimeout = timeout
  1909  		tc := ts.connect()
  1910  		tc.greet()
  1911  
  1912  		reqStream := tc.newStream(streamTypeRequest)
  1913  		reqStream.writeHeaders(requestHeader(nil))
  1914  		call := tc.nextHandlerCall()
  1915  		body := make([]byte, defaultBodyBufferCap+1)
  1916  
  1917  		// Write within the server handler should succeed prior to timeout.
  1918  		time.Sleep(timeout - 1)
  1919  		synctest.Wait()
  1920  		if _, err := call.w.Write(body); err != nil {
  1921  			t.Errorf("Write() before timeout = %v, want nil", err)
  1922  		}
  1923  		call.w.(http.Flusher).Flush()
  1924  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
  1925  		reqStream.wantData(body)
  1926  		reqStream.wantIdle("timeout has not been reached")
  1927  
  1928  		// Write within the server handler should fail once timeout is reached.
  1929  		// A stream error should also be sent to the client.
  1930  		time.Sleep(1)
  1931  		synctest.Wait()
  1932  		if _, err := call.w.Write(body); !errors.Is(err, os.ErrDeadlineExceeded) {
  1933  			t.Errorf("Write() after timeout = %v, want os.ErrDeadlineExceeded", err)
  1934  		}
  1935  		call.exit()
  1936  		reqStream.wantError(quic.StreamError(errH3RequestCancelled))
  1937  	})
  1938  }
  1939  
  1940  func TestServerWriteTimeoutInProgress(t *testing.T) {
  1941  	synctest.Test(t, func(t *testing.T) {
  1942  		timeout := 10 * time.Second
  1943  		ts := newTestServer(t, nil)
  1944  		ts.s.srv1.WriteTimeout = timeout
  1945  		tc := ts.connect()
  1946  		tc.greet()
  1947  
  1948  		reqStream := tc.newStream(streamTypeRequest)
  1949  		reqStream.writeHeaders(requestHeader(nil))
  1950  		reqStream.Flush()
  1951  		call := tc.nextHandlerCall()
  1952  
  1953  		// Keep writing body endlessly. Eventually, it will get blocked due to
  1954  		// flow control, and start advancing synctest's time.
  1955  		start := time.Now()
  1956  		var err error
  1957  		for err == nil {
  1958  			_, err = call.w.Write([]byte("endless body"))
  1959  		}
  1960  		if !errors.Is(err, os.ErrDeadlineExceeded) {
  1961  			t.Errorf("Write error = %v, want os.ErrDeadlineExceeded", err)
  1962  		}
  1963  		if got, want := time.Since(start), timeout; got != want {
  1964  			t.Errorf("Write blocked for %v, want %v", got, want)
  1965  		}
  1966  		call.exit()
  1967  	})
  1968  }
  1969  
  1970  type testServer struct {
  1971  	t           testing.TB
  1972  	s           *server
  1973  	tn          testNet
  1974  	testHandler *testServerHandler
  1975  	*testQUICEndpoint
  1976  
  1977  	addr netip.AddrPort
  1978  }
  1979  
  1980  type testQUICEndpoint struct {
  1981  	t testing.TB
  1982  	e *quic.Endpoint
  1983  }
  1984  
  1985  type testServerConn struct {
  1986  	ts *testServer
  1987  
  1988  	*testQUICConn
  1989  	control   *testQUICStream
  1990  	localAddr netip.AddrPort
  1991  }
  1992  
  1993  type testServerHandler struct {
  1994  	ts      *testServer
  1995  	callsMu sync.Mutex
  1996  	calls   []*serverHandlerCall
  1997  }
  1998  
  1999  // serverHandlerCall is a call to testServerHandler's ServeHTTP method.
  2000  type serverHandlerCall struct {
  2001  	w         http.ResponseWriter
  2002  	req       *http.Request
  2003  	closeOnce sync.Once
  2004  	ch        chan func()
  2005  }
  2006  
  2007  func newTestServer(t testing.TB, handler http.Handler) *testServer {
  2008  	t.Helper()
  2009  	ts := &testServer{
  2010  		t: t,
  2011  	}
  2012  	if handler == nil {
  2013  		ts.testHandler = &testServerHandler{
  2014  			ts:    ts,
  2015  			calls: []*serverHandlerCall{},
  2016  		}
  2017  		handler = ts.testHandler
  2018  	}
  2019  	ts.s = &server{
  2020  		srv1: &http.Server{},
  2021  	}
  2022  	e := ts.tn.newQUICEndpoint(t, &quic.Config{
  2023  		TLSConfig: testTLSConfig,
  2024  	})
  2025  	ts.addr = e.LocalAddr()
  2026  	go ts.s.serve(t.Context(), e, handler)
  2027  	return ts
  2028  }
  2029  
  2030  func (ts *testServer) connect() *testServerConn {
  2031  	ts.t.Helper()
  2032  	config := &quic.Config{TLSConfig: testTLSConfig}
  2033  	e := ts.tn.newQUICEndpoint(ts.t, nil)
  2034  	qconn, err := e.Dial(ts.t.Context(), "udp", ts.addr.String(), config)
  2035  	if err != nil {
  2036  		ts.t.Fatal(err)
  2037  	}
  2038  	tc := &testServerConn{
  2039  		ts:           ts,
  2040  		testQUICConn: newTestQUICConn(ts.t, qconn),
  2041  		localAddr:    e.LocalAddr(),
  2042  	}
  2043  	synctest.Wait()
  2044  	return tc
  2045  }
  2046  
  2047  // greet performs initial connection handshaking with the server.
  2048  func (tc *testServerConn) greet() {
  2049  	// Client creates a control stream.
  2050  	tc.control = tc.newStream(streamTypeControl)
  2051  	tc.control.writeVarint(int64(frameTypeSettings))
  2052  	tc.control.writeVarint(0) // size
  2053  	tc.control.Flush()
  2054  	synctest.Wait()
  2055  }
  2056  
  2057  // nextHandlerCall returns the next handler call that has been initiated by tc.
  2058  // If there is no handler call, nil is returned.
  2059  func (tc *testServerConn) nextHandlerCall() *serverHandlerCall {
  2060  	h := tc.ts.testHandler
  2061  	if h == nil {
  2062  		tc.t.Fatal("nextHandlerCall is called for a testServer with non-nil handler")
  2063  	}
  2064  	tc.t.Helper()
  2065  	synctest.Wait()
  2066  	h.callsMu.Lock()
  2067  	defer h.callsMu.Unlock()
  2068  	for i, call := range h.calls {
  2069  		if call.req.RemoteAddr == tc.localAddr.String() {
  2070  			h.calls = append(h.calls[:i], h.calls[i+1:]...)
  2071  			return call
  2072  		}
  2073  	}
  2074  	return nil
  2075  }
  2076  
  2077  func (h *testServerHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
  2078  	call := &serverHandlerCall{
  2079  		w:   w,
  2080  		req: req,
  2081  		ch:  make(chan func()),
  2082  	}
  2083  	h.ts.t.Cleanup(call.exit)
  2084  	h.callsMu.Lock()
  2085  	h.calls = append(h.calls, call)
  2086  	h.callsMu.Unlock()
  2087  	for f := range call.ch {
  2088  		f()
  2089  	}
  2090  }
  2091  
  2092  // do executes f in the handler's goroutine.
  2093  func (call *serverHandlerCall) do(f func(http.ResponseWriter, *http.Request)) {
  2094  	donec := make(chan struct{})
  2095  	call.ch <- func() {
  2096  		defer close(donec)
  2097  		f(call.w, call.req)
  2098  	}
  2099  	<-donec
  2100  }
  2101  
  2102  // exit causes the handler to return.
  2103  func (call *serverHandlerCall) exit() {
  2104  	call.closeOnce.Do(func() {
  2105  		close(call.ch)
  2106  	})
  2107  }
  2108  

View as plain text