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  		h                   http.Header
   549  		valid               bool
   550  		maxHeaderBytes      int
   551  		maxHeaderValueCount int
   552  	}{{
   553  		name: "within limits",
   554  		h: http.Header{
   555  			"x-foo": {strings.Repeat("x", 1000)},
   556  		},
   557  		maxHeaderBytes: 1500,
   558  		valid:          true,
   559  	}, {
   560  		name: "too many header bytes",
   561  		h: http.Header{
   562  			"x-foo": {strings.Repeat("x", 1000)},
   563  			"x-bar": {strings.Repeat("x", 1000)},
   564  		},
   565  		maxHeaderBytes: 1500,
   566  	}, {
   567  		name: "field count within limit",
   568  		h: http.Header{
   569  			// :method, :scheme, :path, plus:
   570  			"x-foo": {"4"},
   571  			"x-bar": {"5"},
   572  		},
   573  		maxHeaderBytes:      1500,
   574  		maxHeaderValueCount: 5,
   575  		valid:               true,
   576  	}, {
   577  		name: "field count over limit",
   578  		h: http.Header{
   579  			// :method, :scheme, :path, plus:
   580  			"x-foo": {"4"},
   581  			"x-bar": {"5"},
   582  		},
   583  		maxHeaderBytes:      1500,
   584  		maxHeaderValueCount: 4,
   585  	}} {
   586  		synctestSubtest(t, test.name, func(t *testing.T) {
   587  			if test.maxHeaderValueCount != 0 {
   588  				t.Skip("TODO: when we support only go1.27")
   589  			}
   590  			ts := newTestServer(t, nil)
   591  			ts.s.srv1.MaxHeaderBytes = test.maxHeaderBytes
   592  			// TODO: When we only support go1.27.
   593  			//ts.s.srv1.MaxHeaderValueCount = test.maxHeaderValueCount
   594  			tc := ts.connect()
   595  			tc.greet()
   596  
   597  			reqStream := tc.newStream(streamTypeRequest)
   598  			reqStream.writeHeaders(requestHeader(test.h))
   599  			if test.valid {
   600  				call := tc.nextHandlerCall()
   601  				if call == nil {
   602  					t.Fatal("no server handler call; want one")
   603  				}
   604  			} else {
   605  				reqStream.wantError(quic.StreamError(errH3RequestRejected))
   606  			}
   607  		})
   608  	}
   609  }
   610  
   611  func TestServerBody(t *testing.T) {
   612  	synctest.Test(t, func(t *testing.T) {
   613  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   614  			body, err := io.ReadAll(r.Body)
   615  			if err != nil {
   616  				t.Fatal(err)
   617  			}
   618  			w.Write([]byte(r.URL.Path)) // Implicitly calls w.WriteHeader(200).
   619  			w.Write(body)
   620  		}))
   621  		tc := ts.connect()
   622  		tc.greet()
   623  
   624  		reqStream := tc.newStream(streamTypeRequest)
   625  		reqStream.writeHeaders(requestHeader(nil))
   626  		bodyContent := []byte("some body content that should be echoed")
   627  		reqStream.writeData(bodyContent)
   628  		reqStream.CloseWrite()
   629  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
   630  		// Small multiple calls to Write will be coalesced into one DATA frame.
   631  		reqStream.wantData(append([]byte("/"), bodyContent...))
   632  		reqStream.wantClosed("request is complete")
   633  	})
   634  }
   635  
   636  func TestServerHeadResponseNoBody(t *testing.T) {
   637  	bodyContent := []byte("response body that will not be sent for HEAD requests")
   638  	synctest.Test(t, func(t *testing.T) {
   639  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   640  			w.Write(bodyContent)
   641  		}))
   642  		tc := ts.connect()
   643  		tc.greet()
   644  
   645  		reqStream := tc.newStream(streamTypeRequest)
   646  		reqStream.writeHeaders(requestHeader(nil))
   647  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
   648  		reqStream.wantData(bodyContent)
   649  		reqStream.wantClosed("request is complete")
   650  
   651  		reqStream = tc.newStream(streamTypeRequest)
   652  		reqStream.writeHeaders(requestHeader(http.Header{":method": {http.MethodHead}}))
   653  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
   654  		reqStream.wantClosed("request is complete")
   655  	})
   656  }
   657  
   658  func TestServerShutdownGoaway(t *testing.T) {
   659  	synctest.Test(t, func(t *testing.T) {
   660  		ts := newTestServer(t, nil)
   661  
   662  		tc := ts.connect()
   663  		tc.greet()
   664  		tc.wantNotClosed("after initial connection handshake")
   665  
   666  		requestCount := int64(5)
   667  		for range requestCount {
   668  			tc.newStream(streamTypeRequest).writeHeaders(requestHeader(nil))
   669  		}
   670  
   671  		control := tc.wantStream(streamTypeControl)
   672  		control.wantSettings(nil)
   673  
   674  		shutdownComplete := make(chan any)
   675  		go func() {
   676  			ts.s.shutdown(t.Context())
   677  			shutdownComplete <- struct{}{}
   678  		}()
   679  		control.wantGoaway((requestCount - 1) * 4) // Request stream ID goes from 0, 4, 8, ...
   680  		<-shutdownComplete
   681  	})
   682  }
   683  
   684  func TestServerHandlerEmpty(t *testing.T) {
   685  	synctest.Test(t, func(t *testing.T) {
   686  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   687  			// Empty handler should return a 200 OK
   688  		}))
   689  		tc := ts.connect()
   690  		tc.greet()
   691  
   692  		reqStream := tc.newStream(streamTypeRequest)
   693  		reqStream.writeHeaders(requestHeader(nil))
   694  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
   695  		reqStream.wantClosed("request is complete")
   696  	})
   697  }
   698  
   699  func TestServerHandlerFlushing(t *testing.T) {
   700  	synctest.Test(t, func(t *testing.T) {
   701  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   702  			time.Sleep(time.Second)
   703  			w.Write([]byte("first"))
   704  
   705  			time.Sleep(time.Second)
   706  			w.Write([]byte("second"))
   707  			w.(http.Flusher).Flush()
   708  
   709  			time.Sleep(time.Second)
   710  			w.Write([]byte("third"))
   711  		}))
   712  		tc := ts.connect()
   713  		tc.greet()
   714  
   715  		reqStream := tc.newStream(streamTypeRequest)
   716  		reqStream.writeHeaders(requestHeader(nil))
   717  		respBody := make([]byte, 100)
   718  
   719  		time.Sleep(time.Second)
   720  		synctest.Wait()
   721  		if n, err := reqStream.Read(respBody); err == nil {
   722  			t.Errorf("got %v bytes read, want no message yet", n)
   723  		}
   724  
   725  		time.Sleep(time.Second)
   726  		synctest.Wait()
   727  		if _, err := reqStream.Read(respBody); err != nil {
   728  			t.Errorf("failed to read partial response from server, got err: %v", err)
   729  		}
   730  
   731  		time.Sleep(time.Second)
   732  		synctest.Wait()
   733  		if _, err := reqStream.Read(respBody); err != io.EOF {
   734  			t.Errorf("got err %v, want EOF", err)
   735  		}
   736  		reqStream.wantClosed("request is complete")
   737  	})
   738  }
   739  
   740  func TestServerHandlerStreaming(t *testing.T) {
   741  	synctest.Test(t, func(t *testing.T) {
   742  		stream := make(chan string)
   743  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   744  			// Flushing when we have not written anything yet implicitly calls
   745  			// w.WriteHeader(200).
   746  			w.(http.Flusher).Flush()
   747  			for str := range stream {
   748  				w.Write([]byte(str))
   749  				w.(http.Flusher).Flush()
   750  			}
   751  		}))
   752  		tc := ts.connect()
   753  		tc.greet()
   754  
   755  		reqStream := tc.newStream(streamTypeRequest)
   756  		reqStream.writeHeaders(requestHeader(nil))
   757  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
   758  
   759  		for _, data := range []string{"a", "bunch", "of", "things", "to", "stream"} {
   760  			stream <- data
   761  			reqStream.wantData([]byte(data))
   762  		}
   763  		close(stream)
   764  		reqStream.wantClosed("request is complete")
   765  	})
   766  }
   767  
   768  func TestServerHandlerDeclaresContentLength(t *testing.T) {
   769  	tests := []struct {
   770  		name             string
   771  		contentLen       string
   772  		actualContentLen int
   773  		wantWrittenLen   int
   774  		wantTrimmed      bool
   775  		wantCLHeader     bool
   776  	}{
   777  		{
   778  			name:             "accurate content length",
   779  			contentLen:       "100",
   780  			actualContentLen: 100,
   781  			wantWrittenLen:   100,
   782  			wantCLHeader:     true,
   783  		},
   784  		{
   785  			name:             "larger content length",
   786  			contentLen:       "100",
   787  			actualContentLen: 10,
   788  			wantWrittenLen:   10,
   789  			wantCLHeader:     true,
   790  		},
   791  		{
   792  			name:             "smaller content length",
   793  			contentLen:       "10",
   794  			actualContentLen: 100,
   795  			wantWrittenLen:   10,
   796  			wantTrimmed:      true,
   797  			wantCLHeader:     true,
   798  		},
   799  		{
   800  			name:             "non-numeric string",
   801  			contentLen:       "intentional gibberish",
   802  			actualContentLen: 100,
   803  			wantWrittenLen:   100,
   804  		},
   805  		{
   806  			name:             "negative number",
   807  			contentLen:       "-10",
   808  			actualContentLen: 100,
   809  			wantWrittenLen:   100,
   810  		},
   811  		{
   812  			name:             "plus sign",
   813  			contentLen:       "+10",
   814  			actualContentLen: 100,
   815  			wantWrittenLen:   100,
   816  		},
   817  		{
   818  			name:             "empty",
   819  			contentLen:       "",
   820  			actualContentLen: 100,
   821  			wantWrittenLen:   100,
   822  		},
   823  		{
   824  			name:             "large valid content length",
   825  			contentLen:       "3000000000",
   826  			actualContentLen: 100,
   827  			wantWrittenLen:   100,
   828  			wantCLHeader:     true,
   829  		},
   830  		{
   831  			name:             "content length overflowing int64",
   832  			contentLen:       "9223372036854775808",
   833  			actualContentLen: 100,
   834  			wantWrittenLen:   100,
   835  		},
   836  	}
   837  
   838  	for _, tt := range tests {
   839  		synctestSubtest(t, tt.name, func(t *testing.T) {
   840  			ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   841  				w.Header().Set("Content-Length", tt.contentLen)
   842  				var written int
   843  				var lastErr error
   844  				for range tt.actualContentLen {
   845  					n, err := w.Write([]byte("a"))
   846  					written += n
   847  					lastErr = err
   848  				}
   849  				if tt.wantTrimmed != (lastErr != nil) {
   850  					t.Errorf("got %v error when writing response body, even though wantTrimmed is %v", lastErr, tt.wantTrimmed)
   851  				}
   852  				if written != tt.wantWrittenLen {
   853  					t.Errorf("got %v bytes written by the server, want %v bytes", written, tt.wantWrittenLen)
   854  				}
   855  			}))
   856  			tc := ts.connect()
   857  			tc.greet()
   858  
   859  			reqStream := tc.newStream(streamTypeRequest)
   860  			reqStream.writeHeaders(requestHeader(nil))
   861  			expectedHeaders := http.Header{
   862  				":status":      {"200"},
   863  				"Content-Type": {"text/plain; charset=utf-8"},
   864  				"Date":         {"Sat, 01 Jan 2000 00:00:00 GMT"}, // Synctest starting time.
   865  			}
   866  			if tt.wantCLHeader {
   867  				expectedHeaders.Set("Content-Length", tt.contentLen)
   868  			}
   869  			reqStream.wantHeaders(expectedHeaders)
   870  			reqStream.wantData(slices.Repeat([]byte("a"), tt.wantWrittenLen))
   871  			reqStream.wantClosed("request is complete")
   872  		})
   873  	}
   874  }
   875  
   876  func TestServerExpect100Continue(t *testing.T) {
   877  	synctest.Test(t, func(t *testing.T) {
   878  		streamIdle := make(chan bool)
   879  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   880  			// Expect: 100-continue header should not be accessible from the
   881  			// server handler.
   882  			if len(r.Header) > 0 {
   883  				t.Errorf("got %v, want request header to be empty", r.Header)
   884  			}
   885  			// Reading the body will cause the server to call w.WriteHeader(100).
   886  			<-streamIdle
   887  			body, err := io.ReadAll(r.Body)
   888  			if err != nil {
   889  				t.Fatal(err)
   890  			}
   891  			// Implicitly calls w.WriteHeader(200) since non-1XX status code
   892  			// has been sent yet so far.
   893  			w.Write(body)
   894  		}))
   895  		tc := ts.connect()
   896  		tc.greet()
   897  
   898  		// Client sends an Expect: 100-continue request.
   899  		reqStream := tc.newStream(streamTypeRequest)
   900  		reqStream.writeHeaders(requestHeader(http.Header{
   901  			"expect": {"100-continue"},
   902  		}))
   903  
   904  		reqStream.wantIdle("stream is idle until server sends an HTTP 100 status")
   905  		streamIdle <- true
   906  		// Wait until server responds with HTTP status 100 before sending the
   907  		// body.
   908  		reqStream.wantSomeHeaders(http.Header{":status": {"100"}})
   909  		body := []byte("body that will be echoed back if we get status 100")
   910  		reqStream.writeData(body)
   911  		reqStream.CloseWrite()
   912  
   913  		// Receive the server's response after sending the body.
   914  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
   915  		reqStream.wantData(body)
   916  		reqStream.wantClosed("request is complete")
   917  	})
   918  }
   919  
   920  func TestServerExpect100ContinueSentManually(t *testing.T) {
   921  	synctest.Test(t, func(t *testing.T) {
   922  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   923  			w.WriteHeader(100)
   924  			body, err := io.ReadAll(r.Body) // Should not send another 100.
   925  			if err != nil {
   926  				t.Fatal(err)
   927  			}
   928  			w.Write(body)
   929  		}))
   930  		tc := ts.connect()
   931  		tc.greet()
   932  
   933  		// Client sends an Expect: 100-continue request.
   934  		reqStream := tc.newStream(streamTypeRequest)
   935  		reqStream.writeHeaders(requestHeader(http.Header{
   936  			"expect": {"100-continue"},
   937  		}))
   938  
   939  		// Send the body once the server responds with HTTP status 100.
   940  		reqStream.wantSomeHeaders(http.Header{":status": {"100"}})
   941  		body := []byte("body that will be echoed back")
   942  		reqStream.writeData(body)
   943  		reqStream.CloseWrite()
   944  
   945  		// Verify that the server responds with 200, rather than another 100.
   946  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
   947  		reqStream.wantData(body)
   948  		reqStream.wantClosed("request is complete")
   949  	})
   950  }
   951  
   952  func TestServerExpect100ContinueRejected(t *testing.T) {
   953  	synctest.Test(t, func(t *testing.T) {
   954  		rejectBody := []byte("not allowed")
   955  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   956  			w.WriteHeader(403)
   957  			w.Write(rejectBody)
   958  		}))
   959  		tc := ts.connect()
   960  		tc.greet()
   961  
   962  		// Client sends an Expect: 100-continue request.
   963  		reqStream := tc.newStream(streamTypeRequest)
   964  		reqStream.writeHeaders(requestHeader(http.Header{
   965  			"expect": {"100-continue"},
   966  		}))
   967  
   968  		// Server rejects it.
   969  		reqStream.wantSomeHeaders(http.Header{":status": {"403"}})
   970  		reqStream.wantData(rejectBody)
   971  		reqStream.wantClosed("request is complete")
   972  	})
   973  }
   974  
   975  func TestServer100ContinueBodyReadAfterFinalResponse(t *testing.T) {
   976  	synctest.Test(t, func(t *testing.T) {
   977  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   978  			w.WriteHeader(200)
   979  			w.(http.Flusher).Flush()
   980  			// Read should not cause an HTTP 100 status to be sent since we
   981  			// have sent an HTTP 200 response already.
   982  			// Read should also return an error and should not hang.
   983  			if _, err := io.ReadAll(r.Body); err == nil {
   984  				t.Errorf("got %v, want an error", err)
   985  			}
   986  		}))
   987  		tc := ts.connect()
   988  		tc.greet()
   989  
   990  		// Client sends an Expect: 100-continue request.
   991  		reqStream := tc.newStream(streamTypeRequest)
   992  		reqStream.writeHeaders(requestHeader(http.Header{
   993  			"expect": {"100-continue"},
   994  		}))
   995  
   996  		// Verify that no HTTP 100 was sent.
   997  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
   998  		reqStream.wantClosed("request is complete")
   999  	})
  1000  }
  1001  
  1002  func TestServer100ContinueBodyReadAfter100AndFinalResponse(t *testing.T) {
  1003  	synctest.Test(t, func(t *testing.T) {
  1004  		body := []byte("client body")
  1005  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1006  			w.WriteHeader(100)
  1007  			w.WriteHeader(200)
  1008  			w.(http.Flusher).Flush()
  1009  			// Allow Read to succeed since the handler has sent 100 prior to 200.
  1010  			if gotBody, err := io.ReadAll(r.Body); err != nil || string(gotBody) != string(body) {
  1011  				t.Errorf("io.ReadAll(r.Body) = %v, %v; want %v, nil", gotBody, err, body)
  1012  			}
  1013  		}))
  1014  		tc := ts.connect()
  1015  		tc.greet()
  1016  
  1017  		// Client sends an Expect: 100-continue request.
  1018  		reqStream := tc.newStream(streamTypeRequest)
  1019  		reqStream.writeHeaders(requestHeader(http.Header{
  1020  			"expect": {"100-continue"},
  1021  		}))
  1022  
  1023  		// Send the body once the server responds with HTTP status 100.
  1024  		reqStream.wantSomeHeaders(http.Header{":status": {"100"}})
  1025  		reqStream.writeData(body)
  1026  		reqStream.CloseWrite()
  1027  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
  1028  		reqStream.wantClosed("request is complete")
  1029  	})
  1030  }
  1031  
  1032  func TestServerHandlerReadReqWithNoBody(t *testing.T) {
  1033  	synctest.Test(t, func(t *testing.T) {
  1034  		serverBody := []byte("hello from server!")
  1035  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1036  			if _, err := io.ReadAll(r.Body); err != nil {
  1037  				t.Errorf("got %v err when reading from an empty request body, want nil", err)
  1038  			}
  1039  			w.Write(serverBody)
  1040  		}))
  1041  		tc := ts.connect()
  1042  		tc.greet()
  1043  
  1044  		// Case 1: we know that there is no body / DATA frame because the
  1045  		// client closes the write direction of the stream.
  1046  		reqStream := tc.newStream(streamTypeRequest)
  1047  		reqStream.writeHeaders(requestHeader(nil))
  1048  		reqStream.CloseWrite()
  1049  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
  1050  		reqStream.wantData(serverBody)
  1051  		reqStream.wantClosed("request is complete")
  1052  
  1053  		// Case 2: we know that there is no body / DATA frame because the
  1054  		// client indicates a Content-Length of 0.
  1055  		reqStream = tc.newStream(streamTypeRequest)
  1056  		reqStream.writeHeaders(requestHeader(http.Header{
  1057  			"content-length": {"0"},
  1058  		}))
  1059  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
  1060  		reqStream.wantData(serverBody)
  1061  		reqStream.wantClosed("request is complete")
  1062  	})
  1063  }
  1064  
  1065  func TestServerHandlerReadTrailer(t *testing.T) {
  1066  	synctest.Test(t, func(t *testing.T) {
  1067  		body := []byte("some body")
  1068  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1069  			wantTrailer := http.Header{
  1070  				"Client-Trailer-A": nil,
  1071  				"Client-Trailer-B": nil,
  1072  			}
  1073  			if !reflect.DeepEqual(r.Trailer, wantTrailer) {
  1074  				t.Errorf("got %v; want trailer to be %v before reading the body", r.Trailer, wantTrailer)
  1075  			}
  1076  			if _, err := io.ReadAll(r.Body); err != nil {
  1077  				t.Fatal(err)
  1078  			}
  1079  			wantTrailer = http.Header{
  1080  				"Client-Trailer-A": {"valuea"},
  1081  				"Client-Trailer-B": {"valueb"},
  1082  			}
  1083  			if !reflect.DeepEqual(r.Trailer, wantTrailer) {
  1084  				t.Errorf("got %v; want trailer to be %v after reading the body", r.Trailer, wantTrailer)
  1085  			}
  1086  			w.WriteHeader(200)
  1087  		}))
  1088  		tc := ts.connect()
  1089  		tc.greet()
  1090  
  1091  		reqStream := tc.newStream(streamTypeRequest)
  1092  		reqStream.writeHeaders(requestHeader(http.Header{
  1093  			"trailer": {"Client-Trailer-A, Client-Trailer-B"},
  1094  		}))
  1095  		reqStream.writeData(body)
  1096  		reqStream.writeHeaders(http.Header{
  1097  			"Client-Trailer-A": {"valuea"},
  1098  			"Client-Trailer-B": {"valueb"},
  1099  			// Server should not accept undeclared trailers.
  1100  			"Undeclared-Trailer": {"undeclared"},
  1101  		})
  1102  		reqStream.wantHeaders(nil)
  1103  		reqStream.wantClosed("request is complete")
  1104  	})
  1105  }
  1106  
  1107  func TestServerHandlerReadTrailerNoBody(t *testing.T) {
  1108  	synctest.Test(t, func(t *testing.T) {
  1109  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1110  			wantTrailer := http.Header{
  1111  				"Client-Trailer-A": nil,
  1112  				"Client-Trailer-B": nil,
  1113  			}
  1114  			if !reflect.DeepEqual(r.Trailer, wantTrailer) {
  1115  				t.Errorf("got %v; want trailer to be %v before reading the body", r.Trailer, wantTrailer)
  1116  			}
  1117  			if _, err := io.ReadAll(r.Body); err != nil {
  1118  				t.Fatal(err)
  1119  			}
  1120  			wantTrailer = http.Header{
  1121  				"Client-Trailer-A": {"valuea"},
  1122  				"Client-Trailer-B": {"valueb"},
  1123  			}
  1124  			if !reflect.DeepEqual(r.Trailer, wantTrailer) {
  1125  				t.Errorf("got %v; want trailer to be %v after reading the body", r.Trailer, wantTrailer)
  1126  			}
  1127  			w.WriteHeader(200)
  1128  		}))
  1129  		tc := ts.connect()
  1130  		tc.greet()
  1131  
  1132  		reqStream := tc.newStream(streamTypeRequest)
  1133  		reqStream.writeHeaders(requestHeader(http.Header{
  1134  			"trailer":        {"Client-Trailer-A, Client-Trailer-B"},
  1135  			"content-length": {"0"},
  1136  		}))
  1137  		reqStream.writeHeaders(http.Header{
  1138  			"Client-Trailer-A": {"valuea"},
  1139  			"Client-Trailer-B": {"valueb"},
  1140  			// Server should not accept undeclared trailers.
  1141  			"Undeclared-Trailer": {"undeclared"},
  1142  		})
  1143  		reqStream.wantHeaders(nil)
  1144  		reqStream.wantClosed("request is complete")
  1145  	})
  1146  }
  1147  
  1148  func TestServerHandlerWriteTrailer(t *testing.T) {
  1149  	synctest.Test(t, func(t *testing.T) {
  1150  		body := []byte("some body")
  1151  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1152  			w.Header().Set("Trailer", "server-trailer-a, server-trailer-b") // Trailer header will be canonicalized.
  1153  			w.Header().Add("Trailer", "Server-Trailer-C")
  1154  
  1155  			w.Write(body)
  1156  
  1157  			w.Header().Set("server-trailer-a", "valuea") // Trailer header will be canonicalized.
  1158  			w.Header().Set("Server-Trailer-C", "valuec") // skipping B
  1159  			// Server should not send undeclared trailers, unless it has the
  1160  			// magic "Trailer:" prefix.
  1161  			w.Header().Set("Server-Trailer-Not-Declared", "should be omitted")
  1162  			w.Header().Set("Trailer:Undeclared-Trailer-Exception", "should be sent")
  1163  		}))
  1164  		tc := ts.connect()
  1165  		tc.greet()
  1166  
  1167  		reqStream := tc.newStream(streamTypeRequest)
  1168  		reqStream.writeHeaders(requestHeader(nil))
  1169  		reqStream.wantSomeHeaders(http.Header{
  1170  			":status": {"200"},
  1171  			"Trailer": {"Server-Trailer-A, Server-Trailer-B, Server-Trailer-C"},
  1172  		})
  1173  		reqStream.wantData(body)
  1174  		reqStream.wantSomeHeaders(http.Header{
  1175  			"Server-Trailer-A":             {"valuea"},
  1176  			"Server-Trailer-C":             {"valuec"},
  1177  			"Undeclared-Trailer-Exception": {"should be sent"},
  1178  		})
  1179  		reqStream.wantClosed("request is complete")
  1180  	})
  1181  }
  1182  
  1183  func TestServerHandlerWriteTrailerNoBody(t *testing.T) {
  1184  	synctest.Test(t, func(t *testing.T) {
  1185  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1186  			w.Header().Set("Trailer", "server-trailer-a, server-trailer-b") // Trailer header will be canonicalized.
  1187  			w.Header().Add("Trailer", "Server-Trailer-C")
  1188  
  1189  			w.(http.Flusher).Flush()
  1190  
  1191  			w.Header().Set("server-trailer-a", "valuea") // Trailer header will be canonicalized.
  1192  			w.Header().Set("Server-Trailer-C", "valuec") // skipping B
  1193  			// Server should not send undeclared trailers without "Trailer:"
  1194  			// prefix.
  1195  			w.Header().Set("Server-Trailer-Not-Declared", "should be omitted")
  1196  			w.Header().Set("Trailer:undeclared-trailer-exception", "should be sent")
  1197  		}))
  1198  		tc := ts.connect()
  1199  		tc.greet()
  1200  
  1201  		reqStream := tc.newStream(streamTypeRequest)
  1202  		reqStream.writeHeaders(requestHeader(nil))
  1203  		reqStream.wantSomeHeaders(http.Header{
  1204  			":status": {"200"},
  1205  			"Trailer": {"Server-Trailer-A, Server-Trailer-B, Server-Trailer-C"},
  1206  		})
  1207  		reqStream.wantSomeHeaders(http.Header{
  1208  			"Server-Trailer-A":             {"valuea"},
  1209  			"Server-Trailer-C":             {"valuec"},
  1210  			"Undeclared-Trailer-Exception": {"should be sent"},
  1211  		})
  1212  		reqStream.wantClosed("request is complete")
  1213  	})
  1214  }
  1215  
  1216  func TestServerInfersHeaders(t *testing.T) {
  1217  	tests := []struct {
  1218  		name            string
  1219  		flushedEarly    bool
  1220  		responseStatus  int
  1221  		does100Continue bool
  1222  		declaredHeader  http.Header
  1223  		want            http.Header
  1224  	}{
  1225  		{
  1226  			name:           "infers undeclared headers",
  1227  			responseStatus: 200,
  1228  			declaredHeader: http.Header{
  1229  				"Some-Other-Header": {"some value"},
  1230  			},
  1231  			want: http.Header{
  1232  				"Date":              {"Sat, 01 Jan 2000 00:00:00 GMT"}, // Synctest starting time.
  1233  				"Content-Type":      {"text/html; charset=utf-8"},
  1234  				"Some-Other-Header": {"some value"},
  1235  			},
  1236  		},
  1237  		{
  1238  			name:           "does not write over declared header",
  1239  			responseStatus: 200,
  1240  			declaredHeader: http.Header{
  1241  				"Date":              {"some date"},
  1242  				"Content-Type":      {"some content type"},
  1243  				"Some-Other-Header": {"some value"},
  1244  			},
  1245  			want: http.Header{
  1246  				"Date":              {"some date"},
  1247  				"Content-Type":      {"some content type"},
  1248  				"Some-Other-Header": {"some value"},
  1249  			},
  1250  		},
  1251  		{
  1252  			name:           "does not infer content type for response with no body",
  1253  			responseStatus: 304, // 304 status response has no body.
  1254  			declaredHeader: http.Header{
  1255  				"Some-Other-Header": {"some value"},
  1256  			},
  1257  			want: http.Header{
  1258  				"Date":              {"Sat, 01 Jan 2000 00:00:00 GMT"}, // Synctest starting time.
  1259  				"Some-Other-Header": {"some value"},
  1260  			},
  1261  		},
  1262  		{
  1263  			// See golang.org/issue/31753.
  1264  			name:           "does not infer content type for response with declared content encoding",
  1265  			responseStatus: 200,
  1266  			declaredHeader: http.Header{
  1267  				"Content-Encoding":  {"some encoding"},
  1268  				"Some-Other-Header": {"some value"},
  1269  			},
  1270  			want: http.Header{
  1271  				"Date":              {"Sat, 01 Jan 2000 00:00:00 GMT"}, // Synctest starting time.
  1272  				"Content-Encoding":  {"some encoding"},
  1273  				"Some-Other-Header": {"some value"},
  1274  			},
  1275  		},
  1276  		{
  1277  			name:           "infers content type for response with empty content encoding",
  1278  			responseStatus: 200,
  1279  			declaredHeader: http.Header{
  1280  				"Content-Encoding":  {""},
  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-Encoding":  {""},
  1286  				"Content-Type":      {"text/html; charset=utf-8"},
  1287  				"Some-Other-Header": {"some value"},
  1288  			},
  1289  		},
  1290  		{
  1291  			name:           "does not infer content type when header is flushed before body is written",
  1292  			responseStatus: 200,
  1293  			flushedEarly:   true,
  1294  			declaredHeader: http.Header{
  1295  				"Some-Other-Header": {"some value"},
  1296  			},
  1297  			want: http.Header{
  1298  				"Date":              {"Sat, 01 Jan 2000 00:00:00 GMT"}, // Synctest starting time.
  1299  				"Some-Other-Header": {"some value"},
  1300  			},
  1301  		},
  1302  		{
  1303  			name:            "infers header for the header that comes after 100 continue",
  1304  			responseStatus:  200,
  1305  			does100Continue: true,
  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  				"Content-Type":      {"text/html; charset=utf-8"},
  1312  				"Some-Other-Header": {"some value"},
  1313  			},
  1314  		},
  1315  	}
  1316  
  1317  	for _, tt := range tests {
  1318  		synctestSubtest(t, tt.name, func(t *testing.T) {
  1319  			body := []byte("<html>some html content</html>")
  1320  			streamIdle := make(chan bool)
  1321  			ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1322  				if tt.does100Continue {
  1323  					<-streamIdle
  1324  					io.ReadAll(r.Body)
  1325  				}
  1326  				for name, values := range tt.declaredHeader {
  1327  					for _, value := range values {
  1328  						w.Header().Add(name, value)
  1329  					}
  1330  				}
  1331  				w.WriteHeader(tt.responseStatus)
  1332  				if tt.flushedEarly {
  1333  					w.(http.Flusher).Flush()
  1334  				}
  1335  				// Write the body one byte at a time. To confirm that body
  1336  				// writes are buffered and that Content-Type will not be
  1337  				// wrongly identified as text/plain rather than text/html.
  1338  				for _, b := range body {
  1339  					w.Write([]byte{b})
  1340  				}
  1341  			}))
  1342  			tc := ts.connect()
  1343  			tc.greet()
  1344  
  1345  			reqStream := tc.newStream(streamTypeRequest)
  1346  
  1347  			if tt.does100Continue {
  1348  				reqStream.writeHeaders(requestHeader(http.Header{
  1349  					"expect": {"100-continue"},
  1350  				}))
  1351  				reqStream.wantIdle("stream is idle until server sends an HTTP 100 status")
  1352  				streamIdle <- true
  1353  				reqStream.wantHeaders(http.Header{":status": {"100"}})
  1354  			}
  1355  
  1356  			reqStream.writeHeaders(requestHeader(nil))
  1357  			tt.want.Add(":status", strconv.Itoa(tt.responseStatus))
  1358  			reqStream.wantHeaders(tt.want)
  1359  			if responseCanHaveBody(tt.responseStatus) {
  1360  				reqStream.wantData(body)
  1361  			}
  1362  			reqStream.wantClosed("request is complete")
  1363  		})
  1364  	}
  1365  }
  1366  
  1367  func TestServerBuffersBodyWrite(t *testing.T) {
  1368  	tests := []struct {
  1369  		name      string
  1370  		bodyLen   int
  1371  		writeSize int
  1372  		flushes   bool
  1373  	}{
  1374  		{
  1375  			name:      "buffers small body content",
  1376  			bodyLen:   defaultBodyBufferCap * 10,
  1377  			writeSize: 5,
  1378  			flushes:   false,
  1379  		},
  1380  		{
  1381  			name:      "does not buffer large body content",
  1382  			bodyLen:   defaultBodyBufferCap * 10,
  1383  			writeSize: defaultBodyBufferCap * 2,
  1384  			flushes:   false,
  1385  		},
  1386  		{
  1387  			name:      "does not buffer flushed body content",
  1388  			bodyLen:   defaultBodyBufferCap * 10,
  1389  			writeSize: 10,
  1390  			flushes:   true,
  1391  		},
  1392  	}
  1393  	for _, tt := range tests {
  1394  		synctestSubtest(t, tt.name, func(t *testing.T) {
  1395  			ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1396  				for n := 0; n < tt.bodyLen; n += tt.writeSize {
  1397  					data := slices.Repeat([]byte("a"), min(tt.writeSize, tt.bodyLen-n))
  1398  					n, err := w.Write(data)
  1399  					if err != nil {
  1400  						t.Fatal(err)
  1401  					}
  1402  					if n != len(data) {
  1403  						t.Errorf("got %v bytes when writing in server handler, want %v", n, len(data))
  1404  					}
  1405  					if tt.flushes {
  1406  						w.(http.Flusher).Flush()
  1407  					}
  1408  				}
  1409  			}))
  1410  			tc := ts.connect()
  1411  			tc.greet()
  1412  
  1413  			reqStream := tc.newStream(streamTypeRequest)
  1414  			reqStream.writeHeaders(requestHeader(nil))
  1415  			reqStream.wantHeaders(nil)
  1416  			switch {
  1417  			case tt.writeSize > defaultBodyBufferCap:
  1418  				// After using the buffer once, it is no longer used since the
  1419  				// writeSize is larger than the buffer.
  1420  				for n := 0; n < tt.bodyLen; n += tt.writeSize {
  1421  					reqStream.wantData(slices.Repeat([]byte("a"), min(tt.writeSize, tt.bodyLen-n)))
  1422  				}
  1423  			case tt.flushes:
  1424  				for n := 0; n < tt.bodyLen; n += tt.writeSize {
  1425  					reqStream.wantData(slices.Repeat([]byte("a"), min(tt.writeSize, tt.bodyLen-n)))
  1426  				}
  1427  			case tt.writeSize <= defaultBodyBufferCap:
  1428  				dataLen := defaultBodyBufferCap + tt.writeSize - (defaultBodyBufferCap % tt.writeSize)
  1429  				for n := 0; n < tt.bodyLen; n += dataLen {
  1430  					reqStream.wantData(slices.Repeat([]byte("a"), min(dataLen, tt.bodyLen-n)))
  1431  				}
  1432  			}
  1433  			reqStream.wantClosed("request is complete")
  1434  		})
  1435  	}
  1436  }
  1437  
  1438  func TestServer103EarlyHints(t *testing.T) {
  1439  	synctest.Test(t, func(t *testing.T) {
  1440  		body := []byte("some body")
  1441  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1442  			h := w.Header()
  1443  
  1444  			h.Add("Content-Length", "123") // Must be ignored
  1445  			h.Add("Link", "</style.css>; rel=preload; as=style")
  1446  			h.Add("Link", "</script.js>; rel=preload; as=script")
  1447  			w.WriteHeader(http.StatusEarlyHints)
  1448  
  1449  			h.Add("Link", "</foo.js>; rel=preload; as=script")
  1450  			w.WriteHeader(http.StatusEarlyHints)
  1451  
  1452  			w.Write(body)                        // Implicitly sends status 200.
  1453  			w.WriteHeader(http.StatusEarlyHints) // Should be a no-op.
  1454  		}))
  1455  		tc := ts.connect()
  1456  		tc.greet()
  1457  
  1458  		reqStream := tc.newStream(streamTypeRequest)
  1459  		reqStream.writeHeaders(requestHeader(nil))
  1460  		reqStream.wantHeaders(http.Header{
  1461  			":status": {"103"},
  1462  			"Link": {
  1463  				"</style.css>; rel=preload; as=style",
  1464  				"</script.js>; rel=preload; as=script",
  1465  			},
  1466  		})
  1467  		reqStream.wantHeaders(http.Header{
  1468  			":status": {"103"},
  1469  			"Link": {
  1470  				"</style.css>; rel=preload; as=style",
  1471  				"</script.js>; rel=preload; as=script",
  1472  				"</foo.js>; rel=preload; as=script",
  1473  			},
  1474  		})
  1475  		reqStream.wantSomeHeaders(http.Header{
  1476  			":status":        {"200"},
  1477  			"Content-Length": {"123"},
  1478  		})
  1479  		reqStream.wantData(body)
  1480  		reqStream.wantClosed("request is complete")
  1481  	})
  1482  }
  1483  
  1484  func TestServer304NotModified(t *testing.T) {
  1485  	synctest.Test(t, func(t *testing.T) {
  1486  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1487  			w.WriteHeader(http.StatusNotModified)
  1488  			if _, err := w.Write([]byte("body should not be allowed")); !errors.Is(err, http.ErrBodyNotAllowed) {
  1489  				t.Errorf("got %v error when calling Write after WriteHeader(304), want %v error", err, http.ErrBodyNotAllowed)
  1490  			}
  1491  		}))
  1492  		tc := ts.connect()
  1493  		tc.greet()
  1494  
  1495  		reqStream := tc.newStream(streamTypeRequest)
  1496  		reqStream.writeHeaders(requestHeader(nil))
  1497  		reqStream.wantSomeHeaders(http.Header{":status": {"304"}})
  1498  		reqStream.wantClosed("request is complete")
  1499  	})
  1500  }
  1501  
  1502  func TestServerInvalidPathHeader(t *testing.T) {
  1503  	for _, test := range []struct {
  1504  		name string
  1505  		path string
  1506  	}{{
  1507  		name: "empty",
  1508  		path: "",
  1509  	}, {
  1510  		name: "invalid char",
  1511  		path: "\x00",
  1512  	}, {
  1513  		name: "absolute url",
  1514  		path: "https://example.com/",
  1515  	}} {
  1516  		synctestSubtest(t, test.name, func(t *testing.T) {
  1517  			ts := newTestServer(t, nil)
  1518  			tc := ts.connect()
  1519  			tc.greet()
  1520  
  1521  			reqStream := tc.newStream(streamTypeRequest)
  1522  			reqStream.writeHeaders(requestHeader(http.Header{
  1523  				":path": []string{test.path},
  1524  			}))
  1525  			reqStream.wantError(quic.StreamError(errH3MessageError))
  1526  		})
  1527  	}
  1528  }
  1529  
  1530  func TestServerOptionsMethod(t *testing.T) {
  1531  	synctest.Test(t, func(t *testing.T) {
  1532  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
  1533  		tc := ts.connect()
  1534  		tc.greet()
  1535  
  1536  		reqStream := tc.newStream(streamTypeRequest)
  1537  		reqStream.writeHeaders(requestHeader(http.Header{
  1538  			":method": []string{"OPTIONS"},
  1539  			":path":   []string{"*"},
  1540  		}))
  1541  		reqStream.wantSomeHeaders(http.Header{
  1542  			":status": {"200"},
  1543  		})
  1544  	})
  1545  }
  1546  
  1547  func TestServerPastWriteDeadline(t *testing.T) {
  1548  	synctest.Test(t, func(t *testing.T) {
  1549  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1550  			ctl := http.NewResponseController(w)
  1551  			io.WriteString(w, "one")
  1552  			if err := ctl.Flush(); err != nil {
  1553  				t.Errorf("Flush() = %v, want nil", err)
  1554  			}
  1555  			time.Sleep(time.Second) // T+1.
  1556  			// Set past write deadline. Write should fail.
  1557  			if err := ctl.SetWriteDeadline(time.Now().Add(-10 * time.Second)); err != nil {
  1558  				t.Errorf("SetWriteDeadline() = %v, want nil", err)
  1559  			}
  1560  			var err error
  1561  			_, err = io.WriteString(w, "x")
  1562  			if err == nil {
  1563  				err = ctl.Flush()
  1564  			}
  1565  			if !errors.Is(err, os.ErrDeadlineExceeded) {
  1566  				t.Errorf("got write err %v, want %v", err, os.ErrDeadlineExceeded)
  1567  			}
  1568  
  1569  			// Extending the write deadline after it's exceeded should have no effect (sticky).
  1570  			if err := ctl.SetWriteDeadline(time.Now().Add(10 * time.Second)); err != nil {
  1571  				t.Errorf("SetWriteDeadline() = %v, want nil", err)
  1572  			}
  1573  			_, err = io.WriteString(w, "x")
  1574  			if err == nil {
  1575  				err = ctl.Flush()
  1576  			}
  1577  			if !errors.Is(err, os.ErrDeadlineExceeded) {
  1578  				t.Errorf("got write err %v (after extend), want %v", err, os.ErrDeadlineExceeded)
  1579  			}
  1580  		}))
  1581  		tc := ts.connect()
  1582  		tc.greet()
  1583  
  1584  		reqStream := tc.newStream(streamTypeRequest)
  1585  		reqStream.writeHeaders(requestHeader(nil))
  1586  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
  1587  		reqStream.wantData([]byte("one"))
  1588  		time.Sleep(2 * time.Second) // T+2.
  1589  		synctest.Wait()
  1590  		reqStream.wantError(quic.StreamError(errH3RequestCancelled))
  1591  	})
  1592  }
  1593  
  1594  func TestServerFutureWriteDeadline(t *testing.T) {
  1595  	synctest.Test(t, func(t *testing.T) {
  1596  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1597  			ctl := http.NewResponseController(w)
  1598  			io.WriteString(w, "one")
  1599  			if err := ctl.Flush(); err != nil {
  1600  				t.Errorf("Flush() = %v, want nil", err)
  1601  			}
  1602  
  1603  			// Set future deadline at T+1. Write should succeed.
  1604  			if err := ctl.SetWriteDeadline(time.Now().Add(time.Second)); err != nil {
  1605  				t.Errorf("SetWriteDeadline() = %v, want nil", err)
  1606  			}
  1607  			io.WriteString(w, "two")
  1608  			if err := ctl.Flush(); err != nil {
  1609  				t.Errorf("Flush() = %v, want nil", err)
  1610  			}
  1611  
  1612  			// Extend deadline to T+3, before it expires.
  1613  			if err := ctl.SetWriteDeadline(time.Now().Add(3 * time.Second)); err != nil {
  1614  				t.Errorf("SetWriteDeadline() = %v, want nil", err)
  1615  			}
  1616  			// Sleep till T+2. Write should succeed since the deadline is T+3.
  1617  			time.Sleep(2 * time.Second)
  1618  			io.WriteString(w, "three")
  1619  			if err := ctl.Flush(); err != nil {
  1620  				t.Errorf("Flush() = %v, want nil", err)
  1621  			}
  1622  
  1623  			// Sleep till T+4. Write should fail since deadline is T+3.
  1624  			time.Sleep(2 * time.Second)
  1625  			var err error
  1626  			_, err = io.WriteString(w, "x")
  1627  			if err == nil {
  1628  				err = ctl.Flush()
  1629  			}
  1630  			if !errors.Is(err, os.ErrDeadlineExceeded) {
  1631  				t.Errorf("got write err %v, want %v", err, os.ErrDeadlineExceeded)
  1632  			}
  1633  
  1634  			// Extending the write deadline after it's exceeded should have no effect (sticky).
  1635  			if err := ctl.SetWriteDeadline(time.Time{}); err != nil {
  1636  				t.Errorf("SetWriteDeadline() = %v, want nil", err)
  1637  			}
  1638  			_, err = io.WriteString(w, "x")
  1639  			if err == nil {
  1640  				err = ctl.Flush()
  1641  			}
  1642  			if !errors.Is(err, os.ErrDeadlineExceeded) {
  1643  				t.Errorf("got write err %v (after extend), want %v", err, os.ErrDeadlineExceeded)
  1644  			}
  1645  		}))
  1646  		tc := ts.connect()
  1647  		tc.greet()
  1648  
  1649  		reqStream := tc.newStream(streamTypeRequest)
  1650  		reqStream.writeHeaders(requestHeader(nil))
  1651  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
  1652  		reqStream.wantData([]byte("one"))
  1653  		reqStream.wantData([]byte("two"))
  1654  		time.Sleep(3 * time.Second) // T+3. After "three" is written.
  1655  		reqStream.wantData([]byte("three"))
  1656  		time.Sleep(3 * time.Second) // T+6. After server exceeds deadline.
  1657  		reqStream.wantError(quic.StreamError(errH3RequestCancelled))
  1658  	})
  1659  }
  1660  
  1661  func TestServerPastReadDeadline(t *testing.T) {
  1662  	synctest.Test(t, func(t *testing.T) {
  1663  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1664  			ctl := http.NewResponseController(w)
  1665  			b := make([]byte, 3)
  1666  			if _, err := io.ReadFull(r.Body, b); err != nil || string(b) != "one" {
  1667  				t.Errorf("Read() got (%q, %v), want (%q, nil)", b, err, "one")
  1668  			}
  1669  			// Set past read deadline. Read should fail.
  1670  			if err := ctl.SetReadDeadline(time.Now().Add(-10 * time.Second)); err != nil {
  1671  				t.Errorf("SetReadDeadline() = %v, want nil", err)
  1672  			}
  1673  			_, err := io.ReadAll(r.Body)
  1674  			if !errors.Is(err, os.ErrDeadlineExceeded) {
  1675  				t.Errorf("got read err %v, want %v", err, os.ErrDeadlineExceeded)
  1676  			}
  1677  
  1678  			// Extending the read deadline after it's exceeded should have no effect (sticky).
  1679  			if err := ctl.SetReadDeadline(time.Now().Add(10 * time.Second)); err != nil {
  1680  				t.Errorf("SetReadDeadline() = %v, want nil", err)
  1681  			}
  1682  			_, err = io.ReadAll(r.Body)
  1683  			if !errors.Is(err, os.ErrDeadlineExceeded) {
  1684  				t.Errorf("got read err %v (after extend), want %v", err, os.ErrDeadlineExceeded)
  1685  			}
  1686  		}))
  1687  		tc := ts.connect()
  1688  		tc.greet()
  1689  
  1690  		reqStream := tc.newStream(streamTypeRequest)
  1691  		reqStream.writeHeaders(requestHeader(nil))
  1692  		reqStream.writeData([]byte("one"))
  1693  		synctest.Wait()
  1694  	})
  1695  }
  1696  
  1697  func TestServerFutureReadDeadline(t *testing.T) {
  1698  	synctest.Test(t, func(t *testing.T) {
  1699  		ts := newTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1700  			ctl := http.NewResponseController(w)
  1701  			b := make([]byte, 3)
  1702  			if _, err := io.ReadFull(r.Body, b); err != nil || string(b) != "one" {
  1703  				t.Errorf("Read() got (%q, %v), want (%q, nil)", b, err, "one")
  1704  			}
  1705  
  1706  			// Set future deadline at T+2s. Read should succeed.
  1707  			if err := ctl.SetReadDeadline(time.Now().Add(2 * time.Second)); err != nil {
  1708  				t.Errorf("SetReadDeadline() = %v, want nil", err)
  1709  			}
  1710  			b2 := make([]byte, 3)
  1711  			if _, err := io.ReadFull(r.Body, b2); err != nil || string(b2) != "two" {
  1712  				t.Errorf("Read() got (%q, %v), want (%q, nil)", b2, err, "two")
  1713  			}
  1714  
  1715  			// Extend deadline to T+5s, before it expires.
  1716  			if err := ctl.SetReadDeadline(time.Now().Add(4 * time.Second)); err != nil {
  1717  				t.Errorf("SetReadDeadline() = %v, want nil", err)
  1718  			}
  1719  			// Sleep till T+3. Read should succeed since the deadline is T+5.
  1720  			time.Sleep(2 * time.Second)
  1721  			b3 := make([]byte, 5)
  1722  			if _, err := io.ReadFull(r.Body, b3); err != nil || string(b3) != "three" {
  1723  				t.Errorf("Read() got (%q, %v), want (%q, nil)", b3, err, "three")
  1724  			}
  1725  
  1726  			// Sleep till T+6. Read should fail since deadline has passed.
  1727  			time.Sleep(3 * time.Second)
  1728  			_, err := io.ReadAll(r.Body)
  1729  			if !errors.Is(err, os.ErrDeadlineExceeded) {
  1730  				t.Errorf("got read err %v, want %v", err, os.ErrDeadlineExceeded)
  1731  			}
  1732  
  1733  			// Extending the read deadline after it's exceeded should have no effect (sticky).
  1734  			if err := ctl.SetReadDeadline(time.Time{}); err != nil {
  1735  				t.Errorf("SetReadDeadline() = %v, want nil", err)
  1736  			}
  1737  			_, err = io.ReadAll(r.Body)
  1738  			if !errors.Is(err, os.ErrDeadlineExceeded) {
  1739  				t.Errorf("got read err %v (after extend), want %v", err, os.ErrDeadlineExceeded)
  1740  			}
  1741  		}))
  1742  		tc := ts.connect()
  1743  		tc.greet()
  1744  
  1745  		reqStream := tc.newStream(streamTypeRequest)
  1746  		reqStream.writeHeaders(requestHeader(nil))
  1747  		reqStream.writeData([]byte("one"))
  1748  
  1749  		time.Sleep(time.Second)
  1750  		reqStream.writeData([]byte("two")) // T+1.
  1751  		synctest.Wait()
  1752  
  1753  		time.Sleep(time.Second)
  1754  		reqStream.writeData([]byte("three")) // T+2.
  1755  		synctest.Wait()
  1756  
  1757  		time.Sleep(4 * time.Second) // Advance to T+6 for server handler to complete.
  1758  	})
  1759  }
  1760  
  1761  func TestServerReadHeaderTimeout(t *testing.T) {
  1762  	synctest.Test(t, func(t *testing.T) {
  1763  		timeout := 10 * time.Second
  1764  		ts := newTestServer(t, nil)
  1765  		ts.s.srv1.ReadHeaderTimeout = timeout
  1766  		tc := ts.connect()
  1767  		tc.greet()
  1768  
  1769  		// Write some part of the header, but never finish sending it.
  1770  		reqStream := tc.newStream(streamTypeRequest)
  1771  		reqStream.writeVarint(int64(frameTypeHeaders))
  1772  		if err := reqStream.Flush(); err != nil {
  1773  			t.Fatalf("Flush() = %v, want nil", err)
  1774  		}
  1775  
  1776  		// A stream error should be sent to the client as soon as the timeout
  1777  		// is reached. Server handler should not be called.
  1778  		time.Sleep(timeout - 1)
  1779  		reqStream.wantIdle("timeout has not been reached")
  1780  		time.Sleep(1)
  1781  		reqStream.wantError(quic.StreamError(errH3RequestRejected))
  1782  		if tc.nextHandlerCall() != nil {
  1783  			t.Error("server handler should not be called")
  1784  		}
  1785  	})
  1786  }
  1787  
  1788  func TestServerReadTimeout(t *testing.T) {
  1789  	synctest.Test(t, func(t *testing.T) {
  1790  		timeout := 10 * time.Second
  1791  		ts := newTestServer(t, nil)
  1792  		ts.s.srv1.ReadTimeout = timeout
  1793  		tc := ts.connect()
  1794  		tc.greet()
  1795  
  1796  		reqStream := tc.newStream(streamTypeRequest)
  1797  		reqStream.writeHeaders(requestHeader(nil))
  1798  		reqStream.writeData([]byte("some body"))
  1799  		call := tc.nextHandlerCall()
  1800  
  1801  		// Read within the server handler should succeed prior to timeout.
  1802  		time.Sleep(timeout - 1)
  1803  		synctest.Wait()
  1804  		if _, err := call.req.Body.Read(make([]byte, 1)); err != nil {
  1805  			t.Errorf("Read() before timeout = %v, want nil", err)
  1806  		}
  1807  
  1808  		// Read within the server handler should fail once timeout is reached.
  1809  		// Stream error should not be sent to the client, as it is up to the
  1810  		// server handler to decide how it wants to deal with its inability to
  1811  		// read the request body.
  1812  		time.Sleep(1)
  1813  		synctest.Wait()
  1814  		if _, err := call.req.Body.Read(make([]byte, 1)); !errors.Is(err, os.ErrDeadlineExceeded) {
  1815  			t.Errorf("Read() after timeout = %v, want os.ErrDeadlineExceeded", err)
  1816  		}
  1817  		call.w.Write([]byte("some body"))
  1818  		call.exit()
  1819  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
  1820  		reqStream.wantData([]byte("some body"))
  1821  		reqStream.wantClosed("clean close expected")
  1822  	})
  1823  }
  1824  
  1825  func TestServerReadTimeoutInProgress(t *testing.T) {
  1826  	synctest.Test(t, func(t *testing.T) {
  1827  		timeout := 10 * time.Second
  1828  		ts := newTestServer(t, nil)
  1829  		ts.s.srv1.ReadTimeout = timeout
  1830  		tc := ts.connect()
  1831  		tc.greet()
  1832  
  1833  		reqStream := tc.newStream(streamTypeRequest)
  1834  		reqStream.writeHeaders(requestHeader(nil))
  1835  		reqStream.Flush()
  1836  		call := tc.nextHandlerCall()
  1837  
  1838  		// Read will block due to the client having sent no body, thus
  1839  		// advancing synctest's time.
  1840  		start := time.Now()
  1841  		_, err := call.req.Body.Read(make([]byte, 1))
  1842  		if !errors.Is(err, os.ErrDeadlineExceeded) {
  1843  			t.Errorf("Read error = %v, want os.ErrDeadlineExceeded", err)
  1844  		}
  1845  		if got, want := time.Since(start), timeout; got != want {
  1846  			t.Errorf("Read blocked for %v, want %v", got, want)
  1847  		}
  1848  		call.exit()
  1849  	})
  1850  }
  1851  
  1852  func TestServerWriteTimeout(t *testing.T) {
  1853  	synctest.Test(t, func(t *testing.T) {
  1854  		timeout := 10 * time.Second
  1855  		ts := newTestServer(t, nil)
  1856  		ts.s.srv1.WriteTimeout = timeout
  1857  		tc := ts.connect()
  1858  		tc.greet()
  1859  
  1860  		reqStream := tc.newStream(streamTypeRequest)
  1861  		reqStream.writeHeaders(requestHeader(nil))
  1862  		call := tc.nextHandlerCall()
  1863  		body := make([]byte, defaultBodyBufferCap+1)
  1864  
  1865  		// Write within the server handler should succeed prior to timeout.
  1866  		time.Sleep(timeout - 1)
  1867  		synctest.Wait()
  1868  		if _, err := call.w.Write(body); err != nil {
  1869  			t.Errorf("Write() before timeout = %v, want nil", err)
  1870  		}
  1871  		call.w.(http.Flusher).Flush()
  1872  		reqStream.wantSomeHeaders(http.Header{":status": {"200"}})
  1873  		reqStream.wantData(body)
  1874  		reqStream.wantIdle("timeout has not been reached")
  1875  
  1876  		// Write within the server handler should fail once timeout is reached.
  1877  		// A stream error should also be sent to the client.
  1878  		time.Sleep(1)
  1879  		synctest.Wait()
  1880  		if _, err := call.w.Write(body); !errors.Is(err, os.ErrDeadlineExceeded) {
  1881  			t.Errorf("Write() after timeout = %v, want os.ErrDeadlineExceeded", err)
  1882  		}
  1883  		call.exit()
  1884  		reqStream.wantError(quic.StreamError(errH3RequestCancelled))
  1885  	})
  1886  }
  1887  
  1888  func TestServerWriteTimeoutInProgress(t *testing.T) {
  1889  	synctest.Test(t, func(t *testing.T) {
  1890  		timeout := 10 * time.Second
  1891  		ts := newTestServer(t, nil)
  1892  		ts.s.srv1.WriteTimeout = timeout
  1893  		tc := ts.connect()
  1894  		tc.greet()
  1895  
  1896  		reqStream := tc.newStream(streamTypeRequest)
  1897  		reqStream.writeHeaders(requestHeader(nil))
  1898  		reqStream.Flush()
  1899  		call := tc.nextHandlerCall()
  1900  
  1901  		// Keep writing body endlessly. Eventually, it will get blocked due to
  1902  		// flow control, and start advancing synctest's time.
  1903  		start := time.Now()
  1904  		var err error
  1905  		for err == nil {
  1906  			_, err = call.w.Write([]byte("endless body"))
  1907  		}
  1908  		if !errors.Is(err, os.ErrDeadlineExceeded) {
  1909  			t.Errorf("Write error = %v, want os.ErrDeadlineExceeded", err)
  1910  		}
  1911  		if got, want := time.Since(start), timeout; got != want {
  1912  			t.Errorf("Write blocked for %v, want %v", got, want)
  1913  		}
  1914  		call.exit()
  1915  	})
  1916  }
  1917  
  1918  type testServer struct {
  1919  	t           testing.TB
  1920  	s           *server
  1921  	tn          testNet
  1922  	testHandler *testServerHandler
  1923  	*testQUICEndpoint
  1924  
  1925  	addr netip.AddrPort
  1926  }
  1927  
  1928  type testQUICEndpoint struct {
  1929  	t testing.TB
  1930  	e *quic.Endpoint
  1931  }
  1932  
  1933  type testServerConn struct {
  1934  	ts *testServer
  1935  
  1936  	*testQUICConn
  1937  	control   *testQUICStream
  1938  	localAddr netip.AddrPort
  1939  }
  1940  
  1941  type testServerHandler struct {
  1942  	ts      *testServer
  1943  	callsMu sync.Mutex
  1944  	calls   []*serverHandlerCall
  1945  }
  1946  
  1947  // serverHandlerCall is a call to testServerHandler's ServeHTTP method.
  1948  type serverHandlerCall struct {
  1949  	w         http.ResponseWriter
  1950  	req       *http.Request
  1951  	closeOnce sync.Once
  1952  	ch        chan func()
  1953  }
  1954  
  1955  func newTestServer(t testing.TB, handler http.Handler) *testServer {
  1956  	t.Helper()
  1957  	ts := &testServer{
  1958  		t: t,
  1959  	}
  1960  	if handler == nil {
  1961  		ts.testHandler = &testServerHandler{
  1962  			ts:    ts,
  1963  			calls: []*serverHandlerCall{},
  1964  		}
  1965  		handler = ts.testHandler
  1966  	}
  1967  	ts.s = &server{
  1968  		srv1: &http.Server{},
  1969  	}
  1970  	e := ts.tn.newQUICEndpoint(t, &quic.Config{
  1971  		TLSConfig: testTLSConfig,
  1972  	})
  1973  	ts.addr = e.LocalAddr()
  1974  	go ts.s.serve(t.Context(), e, handler)
  1975  	return ts
  1976  }
  1977  
  1978  func (ts *testServer) connect() *testServerConn {
  1979  	ts.t.Helper()
  1980  	config := &quic.Config{TLSConfig: testTLSConfig}
  1981  	e := ts.tn.newQUICEndpoint(ts.t, nil)
  1982  	qconn, err := e.Dial(ts.t.Context(), "udp", ts.addr.String(), config)
  1983  	if err != nil {
  1984  		ts.t.Fatal(err)
  1985  	}
  1986  	tc := &testServerConn{
  1987  		ts:           ts,
  1988  		testQUICConn: newTestQUICConn(ts.t, qconn),
  1989  		localAddr:    e.LocalAddr(),
  1990  	}
  1991  	synctest.Wait()
  1992  	return tc
  1993  }
  1994  
  1995  // greet performs initial connection handshaking with the server.
  1996  func (tc *testServerConn) greet() {
  1997  	// Client creates a control stream.
  1998  	tc.control = tc.newStream(streamTypeControl)
  1999  	tc.control.writeVarint(int64(frameTypeSettings))
  2000  	tc.control.writeVarint(0) // size
  2001  	tc.control.Flush()
  2002  	synctest.Wait()
  2003  }
  2004  
  2005  // nextHandlerCall returns the next handler call that has been initiated by tc.
  2006  // If there is no handler call, nil is returned.
  2007  func (tc *testServerConn) nextHandlerCall() *serverHandlerCall {
  2008  	h := tc.ts.testHandler
  2009  	if h == nil {
  2010  		tc.t.Fatal("nextHandlerCall is called for a testServer with non-nil handler")
  2011  	}
  2012  	tc.t.Helper()
  2013  	synctest.Wait()
  2014  	h.callsMu.Lock()
  2015  	defer h.callsMu.Unlock()
  2016  	for i, call := range h.calls {
  2017  		if call.req.RemoteAddr == tc.localAddr.String() {
  2018  			h.calls = append(h.calls[:i], h.calls[i+1:]...)
  2019  			return call
  2020  		}
  2021  	}
  2022  	return nil
  2023  }
  2024  
  2025  func (h *testServerHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
  2026  	call := &serverHandlerCall{
  2027  		w:   w,
  2028  		req: req,
  2029  		ch:  make(chan func()),
  2030  	}
  2031  	h.ts.t.Cleanup(call.exit)
  2032  	h.callsMu.Lock()
  2033  	h.calls = append(h.calls, call)
  2034  	h.callsMu.Unlock()
  2035  	for f := range call.ch {
  2036  		f()
  2037  	}
  2038  }
  2039  
  2040  // do executes f in the handler's goroutine.
  2041  func (call *serverHandlerCall) do(f func(http.ResponseWriter, *http.Request)) {
  2042  	donec := make(chan struct{})
  2043  	call.ch <- func() {
  2044  		defer close(donec)
  2045  		f(call.w, call.req)
  2046  	}
  2047  	<-donec
  2048  }
  2049  
  2050  // exit causes the handler to return.
  2051  func (call *serverHandlerCall) exit() {
  2052  	call.closeOnce.Do(func() {
  2053  		close(call.ch)
  2054  	})
  2055  }
  2056  

View as plain text