Help us shape the future of Go! Take the 2026 Go Developer Survey

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

View as plain text