Source file src/net/http/internal/http2/server_internal_test.go

     1  // Copyright 2026 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 http2
     6  
     7  import (
     8  	"errors"
     9  	"fmt"
    10  	"strings"
    11  	"testing"
    12  )
    13  
    14  func TestCheckValidHTTP2Request(t *testing.T) {
    15  	tests := []struct {
    16  		h    Header
    17  		want error
    18  	}{
    19  		{
    20  			h:    Header{"Te": {"trailers"}},
    21  			want: nil,
    22  		},
    23  		{
    24  			h:    Header{"Te": {"trailers", "bogus"}},
    25  			want: errors.New(`request header "TE" may only be "trailers" in HTTP/2`),
    26  		},
    27  		{
    28  			h:    Header{"Foo": {""}},
    29  			want: nil,
    30  		},
    31  		{
    32  			h:    Header{"Connection": {""}},
    33  			want: errors.New(`request header "Connection" is not valid in HTTP/2`),
    34  		},
    35  		{
    36  			h:    Header{"Proxy-Connection": {""}},
    37  			want: errors.New(`request header "Proxy-Connection" is not valid in HTTP/2`),
    38  		},
    39  		{
    40  			h:    Header{"Keep-Alive": {""}},
    41  			want: errors.New(`request header "Keep-Alive" is not valid in HTTP/2`),
    42  		},
    43  		{
    44  			h:    Header{"Upgrade": {""}},
    45  			want: errors.New(`request header "Upgrade" is not valid in HTTP/2`),
    46  		},
    47  	}
    48  	for i, tt := range tests {
    49  		got := checkValidHTTP2RequestHeaders(tt.h)
    50  		if !equalError(got, tt.want) {
    51  			t.Errorf("%d. checkValidHTTP2Request = %v; want %v", i, got, tt.want)
    52  		}
    53  	}
    54  }
    55  
    56  // TestCanonicalHeaderCacheGrowth verifies that the canonical header cache
    57  // size is capped to a reasonable level.
    58  func TestCanonicalHeaderCacheGrowth(t *testing.T) {
    59  	for _, size := range []int{1, (1 << 20) - 10} {
    60  		base := strings.Repeat("X", size)
    61  		sc := &serverConn{
    62  			serveG: newGoroutineLock(),
    63  		}
    64  		count := 0
    65  		added := 0
    66  		for added < 10*maxCachedCanonicalHeadersKeysSize {
    67  			h := fmt.Sprintf("%v-%v", base, count)
    68  			c := sc.canonicalHeader(h)
    69  			if len(h) != len(c) {
    70  				t.Errorf("sc.canonicalHeader(%q) = %q, want same length", h, c)
    71  			}
    72  			count++
    73  			added += len(h)
    74  		}
    75  		total := 0
    76  		for k, v := range sc.canonHeader {
    77  			total += len(k) + len(v) + 100
    78  		}
    79  		if total > maxCachedCanonicalHeadersKeysSize {
    80  			t.Errorf("after adding %v ~%v-byte headers, canonHeader cache is ~%v bytes, want <%v", count, size, total, maxCachedCanonicalHeadersKeysSize)
    81  		}
    82  	}
    83  }
    84  

View as plain text