Skip to content

net/http: HTTP/2 configuration API #67813

Open
@neild

Description

@neild

This issue is part of a project to move x/net/http2 into std: #67810

Configuring HTTP/2-specific protocol options currently requires users to import the golang.org/x/net/http2 package and call http2.ConfigureServer or http2.ConfigureTransports.

Configuring options in this fashion has the side effect of replacing the bundled HTTP/2 implementation in net/http with the one in golang.org/x/net/http2.

I propose adding HTTP/2 configuration options to net/http, permitting HTTP/2 servers and clients to be configured without importing an external package and separating configuration from version selection.

Many of the HTTP/2 settings are identical for server and client connections. For example, the MaxDecoderHeaderTableSize field of http2.Server and http2.Transport sets the SETTINGS_HEADER_TABLE_SIZE setting sent to the peer. We will unify these settings into a single configuration struct, and add this configuration to http.Server and http.Transport.

type HTTP2Config struct {
	// MaxConcurrentStreams optionally specifies the number of
	// concurrent streams that a peer may have open at a
	// time (SETTINGS_MAX_CONCURRENT_STREAMS).
	// If zero, MaxConcurrentStreams defaults to at least 100.
	MaxConcurrentStreams uint32

	// MaxDecoderHeaderTableSize optionally specifies the http2
	// SETTINGS_HEADER_TABLE_SIZE to send in the initial settings frame. It
	// informs the remote endpoint of the maximum size of the header compression
	// table used to decode header blocks, in octets. If zero, the default value
	// of 4096 is used.
	MaxDecoderHeaderTableSize uint32

	// MaxEncoderHeaderTableSize optionally specifies an upper limit for the
	// header compression table used for encoding request headers. Received
	// SETTINGS_HEADER_TABLE_SIZE settings are capped at this limit. If zero,
	// the default value of 4096 is used.
	MaxEncoderHeaderTableSize uint32

	// MaxReadFrameSize optionally specifies the largest frame
	// this endpoint is willing to read (SETTINGS_MAX_FRAME_SIZE).
	// A valid value is between 16k and 16M, inclusive.
	// If zero or otherwise invalid, a default value is used.
	MaxReadFrameSize uint32

	// MaxUploadBufferPerConnection is the size of the initial flow
	// control window for each connection. The HTTP/2 spec does not
	// allow this to be smaller than 65535 or larger than 2^32-1.
	// If the value is outside this range, a default value will be
	// used instead.
	MaxUploadBufferPerConnection int32

	// MaxUploadBufferPerStream is the size of the initial flow control
	// window for each stream. The HTTP/2 spec does not allow this to
	// be larger than 2^32-1. If the value is zero or larger than the
	// maximum, a default value will be used instead.
	MaxUploadBufferPerStream int32

	// SendPingTimeout is the timeout after which a health check using a ping
	// frame will be carried out if no frame is received on the connection.
	// If zero, no health check is performed.
	SendPingTimeout time.Duration

	// PingTimeout is the timeout after which the connection will be closed
	// if a response to a ping is not received.
	// If zero, a default of 15 seconds is used.
	PingTimeout time.Duration

	// WriteByteTimeout is the timeout after which a connection will be
	// closed if no data can be written to it. The timeout begins when data is
	// available to write, and is extended whenever any bytes are written.
	WriteByteTimeout time.Duration

	// PermitProhibitedCipherSuites, if true, permits the use of
	// cipher suites prohibited by the HTTP/2 spec.
	PermitProhibitedCipherSuites bool

	// CountError, if non-nil, is called on HTTP/2 errors.
	// It's intended to increment a metric for monitoring, such
	// as an expvar or Prometheus metric.
	// The errType consists of only ASCII word characters.
	CountError func(errType string)
}

type Server struct { // contains unchanged fields
	HTTP2 HTTP2Config
}

type Transport struct { // contains unchanged fields
	HTTP2 HTTP2Config
}

The SendPingTImeout and PingTimeout fields assume #67812 is accepted, and the WriteByteTimeout field assumes #67811 is accepted.

The http2.Transport.StrictMaxConcurrentStreams field controls whether a new connection should be opened to a server if an existing connection has exceeded its stream limit. For example, if an HTTP/2 server advertises a stream limit of 100 concurrent streams, then the 101st concurrent stream opened by the client will block waiting for an existing stream to complete when StrictMaxConcurrentStreams is true, or create a new connection when it is false. There is no equivalent to this setting for HTTP/1 connections, which only support a single concurrent request per connection. We will add this setting to http.Transport, since it could be used to configure HTTP/3 connections (if and when we support HTTP/3):

type Transport struct { // contains unchanged fields
	// StrictMaxConcurrentRequests controls whether an HTTP/2 server's
	// concurrency limit should be respected globally.
	// If true, new requests sent when an connection's concurrency limit has been exceeded
	// will block until an existing request completes.
	// If false, an additional connection will be opened if all existing connections are at their limit.
	StrictMaxConcurrentRequests bool
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    Accepted

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions