golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/http2/http2.go (about)

     1  // Copyright 2014 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 implements the HTTP/2 protocol.
     6  //
     7  // This package is low-level and intended to be used directly by very
     8  // few people. Most users will use it indirectly through the automatic
     9  // use by the net/http package (from Go 1.6 and later).
    10  // For use in earlier Go versions see ConfigureServer. (Transport support
    11  // requires Go 1.6 or later)
    12  //
    13  // See https://http2.github.io/ for more information on HTTP/2.
    14  //
    15  // See https://http2.golang.org/ for a test server running this code.
    16  package http2 // import "golang.org/x/net/http2"
    17  
    18  import (
    19  	"bufio"
    20  	"crypto/tls"
    21  	"fmt"
    22  	"io"
    23  	"net/http"
    24  	"os"
    25  	"sort"
    26  	"strconv"
    27  	"strings"
    28  	"sync"
    29  
    30  	"golang.org/x/net/http/httpguts"
    31  )
    32  
    33  var (
    34  	VerboseLogs    bool
    35  	logFrameWrites bool
    36  	logFrameReads  bool
    37  	inTests        bool
    38  )
    39  
    40  func init() {
    41  	e := os.Getenv("GODEBUG")
    42  	if strings.Contains(e, "http2debug=1") {
    43  		VerboseLogs = true
    44  	}
    45  	if strings.Contains(e, "http2debug=2") {
    46  		VerboseLogs = true
    47  		logFrameWrites = true
    48  		logFrameReads = true
    49  	}
    50  }
    51  
    52  const (
    53  	// ClientPreface is the string that must be sent by new
    54  	// connections from clients.
    55  	ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
    56  
    57  	// SETTINGS_MAX_FRAME_SIZE default
    58  	// https://httpwg.org/specs/rfc7540.html#rfc.section.6.5.2
    59  	initialMaxFrameSize = 16384
    60  
    61  	// NextProtoTLS is the NPN/ALPN protocol negotiated during
    62  	// HTTP/2's TLS setup.
    63  	NextProtoTLS = "h2"
    64  
    65  	// https://httpwg.org/specs/rfc7540.html#SettingValues
    66  	initialHeaderTableSize = 4096
    67  
    68  	initialWindowSize = 65535 // 6.9.2 Initial Flow Control Window Size
    69  
    70  	defaultMaxReadFrameSize = 1 << 20
    71  )
    72  
    73  var (
    74  	clientPreface = []byte(ClientPreface)
    75  )
    76  
    77  type streamState int
    78  
    79  // HTTP/2 stream states.
    80  //
    81  // See http://tools.ietf.org/html/rfc7540#section-5.1.
    82  //
    83  // For simplicity, the server code merges "reserved (local)" into
    84  // "half-closed (remote)". This is one less state transition to track.
    85  // The only downside is that we send PUSH_PROMISEs slightly less
    86  // liberally than allowable. More discussion here:
    87  // https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0599.html
    88  //
    89  // "reserved (remote)" is omitted since the client code does not
    90  // support server push.
    91  const (
    92  	stateIdle streamState = iota
    93  	stateOpen
    94  	stateHalfClosedLocal
    95  	stateHalfClosedRemote
    96  	stateClosed
    97  )
    98  
    99  var stateName = [...]string{
   100  	stateIdle:             "Idle",
   101  	stateOpen:             "Open",
   102  	stateHalfClosedLocal:  "HalfClosedLocal",
   103  	stateHalfClosedRemote: "HalfClosedRemote",
   104  	stateClosed:           "Closed",
   105  }
   106  
   107  func (st streamState) String() string {
   108  	return stateName[st]
   109  }
   110  
   111  // Setting is a setting parameter: which setting it is, and its value.
   112  type Setting struct {
   113  	// ID is which setting is being set.
   114  	// See https://httpwg.org/specs/rfc7540.html#SettingFormat
   115  	ID SettingID
   116  
   117  	// Val is the value.
   118  	Val uint32
   119  }
   120  
   121  func (s Setting) String() string {
   122  	return fmt.Sprintf("[%v = %d]", s.ID, s.Val)
   123  }
   124  
   125  // Valid reports whether the setting is valid.
   126  func (s Setting) Valid() error {
   127  	// Limits and error codes from 6.5.2 Defined SETTINGS Parameters
   128  	switch s.ID {
   129  	case SettingEnablePush:
   130  		if s.Val != 1 && s.Val != 0 {
   131  			return ConnectionError(ErrCodeProtocol)
   132  		}
   133  	case SettingInitialWindowSize:
   134  		if s.Val > 1<<31-1 {
   135  			return ConnectionError(ErrCodeFlowControl)
   136  		}
   137  	case SettingMaxFrameSize:
   138  		if s.Val < 16384 || s.Val > 1<<24-1 {
   139  			return ConnectionError(ErrCodeProtocol)
   140  		}
   141  	}
   142  	return nil
   143  }
   144  
   145  // A SettingID is an HTTP/2 setting as defined in
   146  // https://httpwg.org/specs/rfc7540.html#iana-settings
   147  type SettingID uint16
   148  
   149  const (
   150  	SettingHeaderTableSize      SettingID = 0x1
   151  	SettingEnablePush           SettingID = 0x2
   152  	SettingMaxConcurrentStreams SettingID = 0x3
   153  	SettingInitialWindowSize    SettingID = 0x4
   154  	SettingMaxFrameSize         SettingID = 0x5
   155  	SettingMaxHeaderListSize    SettingID = 0x6
   156  )
   157  
   158  var settingName = map[SettingID]string{
   159  	SettingHeaderTableSize:      "HEADER_TABLE_SIZE",
   160  	SettingEnablePush:           "ENABLE_PUSH",
   161  	SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS",
   162  	SettingInitialWindowSize:    "INITIAL_WINDOW_SIZE",
   163  	SettingMaxFrameSize:         "MAX_FRAME_SIZE",
   164  	SettingMaxHeaderListSize:    "MAX_HEADER_LIST_SIZE",
   165  }
   166  
   167  func (s SettingID) String() string {
   168  	if v, ok := settingName[s]; ok {
   169  		return v
   170  	}
   171  	return fmt.Sprintf("UNKNOWN_SETTING_%d", uint16(s))
   172  }
   173  
   174  // validWireHeaderFieldName reports whether v is a valid header field
   175  // name (key). See httpguts.ValidHeaderName for the base rules.
   176  //
   177  // Further, http2 says:
   178  //
   179  //	"Just as in HTTP/1.x, header field names are strings of ASCII
   180  //	characters that are compared in a case-insensitive
   181  //	fashion. However, header field names MUST be converted to
   182  //	lowercase prior to their encoding in HTTP/2. "
   183  func validWireHeaderFieldName(v string) bool {
   184  	if len(v) == 0 {
   185  		return false
   186  	}
   187  	for _, r := range v {
   188  		if !httpguts.IsTokenRune(r) {
   189  			return false
   190  		}
   191  		if 'A' <= r && r <= 'Z' {
   192  			return false
   193  		}
   194  	}
   195  	return true
   196  }
   197  
   198  func httpCodeString(code int) string {
   199  	switch code {
   200  	case 200:
   201  		return "200"
   202  	case 404:
   203  		return "404"
   204  	}
   205  	return strconv.Itoa(code)
   206  }
   207  
   208  // from pkg io
   209  type stringWriter interface {
   210  	WriteString(s string) (n int, err error)
   211  }
   212  
   213  // A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed).
   214  type closeWaiter chan struct{}
   215  
   216  // Init makes a closeWaiter usable.
   217  // It exists because so a closeWaiter value can be placed inside a
   218  // larger struct and have the Mutex and Cond's memory in the same
   219  // allocation.
   220  func (cw *closeWaiter) Init() {
   221  	*cw = make(chan struct{})
   222  }
   223  
   224  // Close marks the closeWaiter as closed and unblocks any waiters.
   225  func (cw closeWaiter) Close() {
   226  	close(cw)
   227  }
   228  
   229  // Wait waits for the closeWaiter to become closed.
   230  func (cw closeWaiter) Wait() {
   231  	<-cw
   232  }
   233  
   234  // bufferedWriter is a buffered writer that writes to w.
   235  // Its buffered writer is lazily allocated as needed, to minimize
   236  // idle memory usage with many connections.
   237  type bufferedWriter struct {
   238  	_  incomparable
   239  	w  io.Writer     // immutable
   240  	bw *bufio.Writer // non-nil when data is buffered
   241  }
   242  
   243  func newBufferedWriter(w io.Writer) *bufferedWriter {
   244  	return &bufferedWriter{w: w}
   245  }
   246  
   247  // bufWriterPoolBufferSize is the size of bufio.Writer's
   248  // buffers created using bufWriterPool.
   249  //
   250  // TODO: pick a less arbitrary value? this is a bit under
   251  // (3 x typical 1500 byte MTU) at least. Other than that,
   252  // not much thought went into it.
   253  const bufWriterPoolBufferSize = 4 << 10
   254  
   255  var bufWriterPool = sync.Pool{
   256  	New: func() interface{} {
   257  		return bufio.NewWriterSize(nil, bufWriterPoolBufferSize)
   258  	},
   259  }
   260  
   261  func (w *bufferedWriter) Available() int {
   262  	if w.bw == nil {
   263  		return bufWriterPoolBufferSize
   264  	}
   265  	return w.bw.Available()
   266  }
   267  
   268  func (w *bufferedWriter) Write(p []byte) (n int, err error) {
   269  	if w.bw == nil {
   270  		bw := bufWriterPool.Get().(*bufio.Writer)
   271  		bw.Reset(w.w)
   272  		w.bw = bw
   273  	}
   274  	return w.bw.Write(p)
   275  }
   276  
   277  func (w *bufferedWriter) Flush() error {
   278  	bw := w.bw
   279  	if bw == nil {
   280  		return nil
   281  	}
   282  	err := bw.Flush()
   283  	bw.Reset(nil)
   284  	bufWriterPool.Put(bw)
   285  	w.bw = nil
   286  	return err
   287  }
   288  
   289  func mustUint31(v int32) uint32 {
   290  	if v < 0 || v > 2147483647 {
   291  		panic("out of range")
   292  	}
   293  	return uint32(v)
   294  }
   295  
   296  // bodyAllowedForStatus reports whether a given response status code
   297  // permits a body. See RFC 7230, section 3.3.
   298  func bodyAllowedForStatus(status int) bool {
   299  	switch {
   300  	case status >= 100 && status <= 199:
   301  		return false
   302  	case status == 204:
   303  		return false
   304  	case status == 304:
   305  		return false
   306  	}
   307  	return true
   308  }
   309  
   310  type httpError struct {
   311  	_       incomparable
   312  	msg     string
   313  	timeout bool
   314  }
   315  
   316  func (e *httpError) Error() string   { return e.msg }
   317  func (e *httpError) Timeout() bool   { return e.timeout }
   318  func (e *httpError) Temporary() bool { return true }
   319  
   320  var errTimeout error = &httpError{msg: "http2: timeout awaiting response headers", timeout: true}
   321  
   322  type connectionStater interface {
   323  	ConnectionState() tls.ConnectionState
   324  }
   325  
   326  var sorterPool = sync.Pool{New: func() interface{} { return new(sorter) }}
   327  
   328  type sorter struct {
   329  	v []string // owned by sorter
   330  }
   331  
   332  func (s *sorter) Len() int           { return len(s.v) }
   333  func (s *sorter) Swap(i, j int)      { s.v[i], s.v[j] = s.v[j], s.v[i] }
   334  func (s *sorter) Less(i, j int) bool { return s.v[i] < s.v[j] }
   335  
   336  // Keys returns the sorted keys of h.
   337  //
   338  // The returned slice is only valid until s used again or returned to
   339  // its pool.
   340  func (s *sorter) Keys(h http.Header) []string {
   341  	keys := s.v[:0]
   342  	for k := range h {
   343  		keys = append(keys, k)
   344  	}
   345  	s.v = keys
   346  	sort.Sort(s)
   347  	return keys
   348  }
   349  
   350  func (s *sorter) SortStrings(ss []string) {
   351  	// Our sorter works on s.v, which sorter owns, so
   352  	// stash it away while we sort the user's buffer.
   353  	save := s.v
   354  	s.v = ss
   355  	sort.Sort(s)
   356  	s.v = save
   357  }
   358  
   359  // validPseudoPath reports whether v is a valid :path pseudo-header
   360  // value. It must be either:
   361  //
   362  //   - a non-empty string starting with '/'
   363  //   - the string '*', for OPTIONS requests.
   364  //
   365  // For now this is only used a quick check for deciding when to clean
   366  // up Opaque URLs before sending requests from the Transport.
   367  // See golang.org/issue/16847
   368  //
   369  // We used to enforce that the path also didn't start with "//", but
   370  // Google's GFE accepts such paths and Chrome sends them, so ignore
   371  // that part of the spec. See golang.org/issue/19103.
   372  func validPseudoPath(v string) bool {
   373  	return (len(v) > 0 && v[0] == '/') || v == "*"
   374  }
   375  
   376  // incomparable is a zero-width, non-comparable type. Adding it to a struct
   377  // makes that struct also non-comparable, and generally doesn't add
   378  // any size (as long as it's first).
   379  type incomparable [0]func()