http.mx raw

   1  // Copyright 2016 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  //go:generate bundle -o=h2_bundle.go -prefix=http2 -tags=!nethttpomithttp2 -import=golang.org/x/net/internal/httpcommon=net/http/internal/httpcommon golang.org/x/net/http2
   6  
   7  package http
   8  
   9  import (
  10  	"io"
  11  	"strconv"
  12  	"bytes"
  13  	"time"
  14  	"unicode/utf8"
  15  
  16  	"golang.org/x/net/http/httpguts"
  17  )
  18  
  19  // Protocols is a set of HTTP protocols.
  20  // The zero value is an empty set of protocols.
  21  //
  22  // The supported protocols are:
  23  //
  24  //   - HTTP1 is the HTTP/1.0 and HTTP/1.1 protocols.
  25  //     HTTP1 is supported on both unsecured TCP and secured TLS connections.
  26  //
  27  //   - HTTP2 is the HTTP/2 protcol over a TLS connection.
  28  //
  29  //   - UnencryptedHTTP2 is the HTTP/2 protocol over an unsecured TCP connection.
  30  type Protocols struct {
  31  	bits uint8
  32  }
  33  
  34  const (
  35  	protoHTTP1 = 1 << iota
  36  	protoHTTP2
  37  	protoUnencryptedHTTP2
  38  )
  39  
  40  // HTTP1 reports whether p includes HTTP/1.
  41  func (p Protocols) HTTP1() bool { return p.bits&protoHTTP1 != 0 }
  42  
  43  // SetHTTP1 adds or removes HTTP/1 from p.
  44  func (p *Protocols) SetHTTP1(ok bool) { p.setBit(protoHTTP1, ok) }
  45  
  46  // HTTP2 reports whether p includes HTTP/2.
  47  func (p Protocols) HTTP2() bool { return p.bits&protoHTTP2 != 0 }
  48  
  49  // SetHTTP2 adds or removes HTTP/2 from p.
  50  func (p *Protocols) SetHTTP2(ok bool) { p.setBit(protoHTTP2, ok) }
  51  
  52  // UnencryptedHTTP2 reports whether p includes unencrypted HTTP/2.
  53  func (p Protocols) UnencryptedHTTP2() bool { return p.bits&protoUnencryptedHTTP2 != 0 }
  54  
  55  // SetUnencryptedHTTP2 adds or removes unencrypted HTTP/2 from p.
  56  func (p *Protocols) SetUnencryptedHTTP2(ok bool) { p.setBit(protoUnencryptedHTTP2, ok) }
  57  
  58  func (p *Protocols) setBit(bit uint8, ok bool) {
  59  	if ok {
  60  		p.bits |= bit
  61  	} else {
  62  		p.bits &^= bit
  63  	}
  64  }
  65  
  66  func (p Protocols) String() string {
  67  	var s [][]byte
  68  	if p.HTTP1() {
  69  		s = append(s, "HTTP1")
  70  	}
  71  	if p.HTTP2() {
  72  		s = append(s, "HTTP2")
  73  	}
  74  	if p.UnencryptedHTTP2() {
  75  		s = append(s, "UnencryptedHTTP2")
  76  	}
  77  	return "{" + bytes.Join(s, ",") + "}"
  78  }
  79  
  80  // incomparable is a zero-width, non-comparable type. Adding it to a struct
  81  // makes that struct also non-comparable, and generally doesn't add
  82  // any size (as long as it's first).
  83  type incomparable [0]func()
  84  
  85  // maxInt64 is the effective "infinite" value for the Server and
  86  // Transport's byte-limiting readers.
  87  const maxInt64 = 1<<63 - 1
  88  
  89  // aLongTimeAgo is a non-zero time, far in the past, used for
  90  // immediate cancellation of network operations.
  91  var aLongTimeAgo = time.Unix(1, 0)
  92  
  93  // omitBundledHTTP2 is set by omithttp2.go when the nethttpomithttp2
  94  // build tag is set. That means h2_bundle.go isn't compiled in and we
  95  // shouldn't try to use it.
  96  var omitBundledHTTP2 bool
  97  
  98  // TODO(bradfitz): move common stuff here. The other files have accumulated
  99  // generic http stuff in random places.
 100  
 101  // contextKey is a value for use with context.WithValue. It's used as
 102  // a pointer so it fits in an interface{} without allocation.
 103  type contextKey struct {
 104  	name string
 105  }
 106  
 107  func (k *contextKey) String() string { return "net/http context value " + k.name }
 108  
 109  // Given a string of the form "host", "host:port", or "[ipv6::address]:port",
 110  // return true if the string includes a port.
 111  func hasPort(s string) bool { return bytes.LastIndex(s, ":") > bytes.LastIndex(s, "]") }
 112  
 113  // removeEmptyPort strips the empty port in ":port" to ""
 114  // as mandated by RFC 3986 Section 6.2.3.
 115  func removeEmptyPort(host string) string {
 116  	if hasPort(host) {
 117  		return bytes.TrimSuffix(host, ":")
 118  	}
 119  	return host
 120  }
 121  
 122  func isNotToken(r rune) bool {
 123  	return !httpguts.IsTokenRune(r)
 124  }
 125  
 126  // isToken reports whether v is a valid token (https://www.rfc-editor.org/rfc/rfc2616#section-2.2).
 127  func isToken(v string) bool {
 128  	// For historical reasons, this function is called ValidHeaderFieldName (see issue #67031).
 129  	return httpguts.ValidHeaderFieldName(v)
 130  }
 131  
 132  // stringContainsCTLByte reports whether s contains any ASCII control character.
 133  func stringContainsCTLByte(s string) bool {
 134  	for i := 0; i < len(s); i++ {
 135  		b := s[i]
 136  		if b < ' ' || b == 0x7f {
 137  			return true
 138  		}
 139  	}
 140  	return false
 141  }
 142  
 143  func hexEscapeNonASCII(s string) string {
 144  	newLen := 0
 145  	for i := 0; i < len(s); i++ {
 146  		if s[i] >= utf8.RuneSelf {
 147  			newLen += 3
 148  		} else {
 149  			newLen++
 150  		}
 151  	}
 152  	if newLen == len(s) {
 153  		return s
 154  	}
 155  	b := []byte{:0:newLen}
 156  	var pos int
 157  	for i := 0; i < len(s); i++ {
 158  		if s[i] >= utf8.RuneSelf {
 159  			if pos < i {
 160  				b = append(b, s[pos:i]...)
 161  			}
 162  			b = append(b, '%')
 163  			b = strconv.AppendInt(b, int64(s[i]), 16)
 164  			pos = i + 1
 165  		}
 166  	}
 167  	if pos < len(s) {
 168  		b = append(b, s[pos:]...)
 169  	}
 170  	return string(b)
 171  }
 172  
 173  // NoBody is an [io.ReadCloser] with no bytes. Read always returns EOF
 174  // and Close always returns nil. It can be used in an outgoing client
 175  // request to explicitly signal that a request has zero bytes.
 176  // An alternative, however, is to simply set [Request.Body] to nil.
 177  var NoBody = noBody{}
 178  
 179  type noBody struct{}
 180  
 181  func (noBody) Read([]byte) (int, error)         { return 0, io.EOF }
 182  func (noBody) Close() error                     { return nil }
 183  func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
 184  
 185  var (
 186  	// verify that an io.Copy from NoBody won't require a buffer:
 187  	_ io.WriterTo   = NoBody
 188  	_ io.ReadCloser = NoBody
 189  )
 190  
 191  // PushOptions describes options for [Pusher.Push].
 192  type PushOptions struct {
 193  	// Method specifies the HTTP method for the promised request.
 194  	// If set, it must be "GET" or "HEAD". Empty means "GET".
 195  	Method string
 196  
 197  	// Header specifies additional promised request headers. This cannot
 198  	// include HTTP/2 pseudo header fields like ":path" and ":scheme",
 199  	// which will be added automatically.
 200  	Header Header
 201  }
 202  
 203  // Pusher is the interface implemented by ResponseWriters that support
 204  // HTTP/2 server push. For more background, see
 205  // https://tools.ietf.org/html/rfc7540#section-8.2.
 206  type Pusher interface {
 207  	// Push initiates an HTTP/2 server push. This constructs a synthetic
 208  	// request using the given target and options, serializes that request
 209  	// into a PUSH_PROMISE frame, then dispatches that request using the
 210  	// server's request handler. If opts is nil, default options are used.
 211  	//
 212  	// The target must either be an absolute path (like "/path") or an absolute
 213  	// URL that contains a valid host and the same scheme as the parent request.
 214  	// If the target is a path, it will inherit the scheme and host of the
 215  	// parent request.
 216  	//
 217  	// The HTTP/2 spec disallows recursive pushes and cross-authority pushes.
 218  	// Push may or may not detect these invalid pushes; however, invalid
 219  	// pushes will be detected and canceled by conforming clients.
 220  	//
 221  	// Handlers that wish to push URL X should call Push before sending any
 222  	// data that may trigger a request for URL X. This avoids a race where the
 223  	// client issues requests for X before receiving the PUSH_PROMISE for X.
 224  	//
 225  	// Push will run in a separate goroutine making the order of arrival
 226  	// non-deterministic. Any required synchronization needs to be implemented
 227  	// by the caller.
 228  	//
 229  	// Push returns ErrNotSupported if the client has disabled push or if push
 230  	// is not supported on the underlying connection.
 231  	Push(target string, opts *PushOptions) error
 232  }
 233  
 234  // HTTP2Config defines HTTP/2 configuration parameters common to
 235  // both [Transport] and [Server].
 236  type HTTP2Config struct {
 237  	// MaxConcurrentStreams optionally specifies the number of
 238  	// concurrent streams that a peer may have open at a time.
 239  	// If zero, MaxConcurrentStreams defaults to at least 100.
 240  	MaxConcurrentStreams int
 241  
 242  	// MaxDecoderHeaderTableSize optionally specifies an upper limit for the
 243  	// size of the header compression table used for decoding headers sent
 244  	// by the peer.
 245  	// A valid value is less than 4MiB.
 246  	// If zero or invalid, a default value is used.
 247  	MaxDecoderHeaderTableSize int
 248  
 249  	// MaxEncoderHeaderTableSize optionally specifies an upper limit for the
 250  	// header compression table used for sending headers to the peer.
 251  	// A valid value is less than 4MiB.
 252  	// If zero or invalid, a default value is used.
 253  	MaxEncoderHeaderTableSize int
 254  
 255  	// MaxReadFrameSize optionally specifies the largest frame
 256  	// this endpoint is willing to read.
 257  	// A valid value is between 16KiB and 16MiB, inclusive.
 258  	// If zero or invalid, a default value is used.
 259  	MaxReadFrameSize int
 260  
 261  	// MaxReceiveBufferPerConnection is the maximum size of the
 262  	// flow control window for data received on a connection.
 263  	// A valid value is at least 64KiB and less than 4MiB.
 264  	// If invalid, a default value is used.
 265  	MaxReceiveBufferPerConnection int
 266  
 267  	// MaxReceiveBufferPerStream is the maximum size of
 268  	// the flow control window for data received on a stream (request).
 269  	// A valid value is less than 4MiB.
 270  	// If zero or invalid, a default value is used.
 271  	MaxReceiveBufferPerStream int
 272  
 273  	// SendPingTimeout is the timeout after which a health check using a ping
 274  	// frame will be carried out if no frame is received on a connection.
 275  	// If zero, no health check is performed.
 276  	SendPingTimeout time.Duration
 277  
 278  	// PingTimeout is the timeout after which a connection will be closed
 279  	// if a response to a ping is not received.
 280  	// If zero, a default of 15 seconds is used.
 281  	PingTimeout time.Duration
 282  
 283  	// WriteByteTimeout is the timeout after which a connection will be
 284  	// closed if no data can be written to it. The timeout begins when data is
 285  	// available to write, and is extended whenever any bytes are written.
 286  	WriteByteTimeout time.Duration
 287  
 288  	// PermitProhibitedCipherSuites, if true, permits the use of
 289  	// cipher suites prohibited by the HTTP/2 spec.
 290  	PermitProhibitedCipherSuites bool
 291  
 292  	// CountError, if non-nil, is called on HTTP/2 errors.
 293  	// It is intended to increment a metric for monitoring.
 294  	// The errType contains only lowercase letters, digits, and underscores
 295  	// (a-z, 0-9, _).
 296  	CountError func(errType string)
 297  }
 298