http2: deprecate Transport and Server

Fixes golang/go#78064

Change-Id: Ia8f5c109b4594ef5a4fca1eacfc0f2da6a6a6964
Reviewed-on: https://go-review.googlesource.com/c/net/+/819740
Auto-Submit: Damien Neil <dneil@google.com>
Reviewed-by: Nicholas Husin <nsh@golang.org>
Reviewed-by: Nicholas Husin <husin@google.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/http2/example_test.go b/http2/example_test.go
new file mode 100644
index 0000000..2e60bba
--- /dev/null
+++ b/http2/example_test.go
@@ -0,0 +1,34 @@
+// Copyright 2026 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+import "net/http"
+
+// To configure an [http.Transport] to use HTTP/2,
+// set the [http.Transport.Protocols] field.
+func ExampleConfigureTransport() {
+	tr := &http.Transport{}
+	tr.Protocols = new(http.Protocols)
+	tr.Protocols.SetHTTP1(true) // enable HTTP/1
+	tr.Protocols.SetHTTP2(true) // enable HTTP/2
+}
+
+// To configure an [http.Transport] to use HTTP/2,
+// set the [http.Transport.Protocols] field.
+func ExampleConfigureTransports() {
+	tr := &http.Transport{}
+	tr.Protocols = new(http.Protocols)
+	tr.Protocols.SetHTTP1(true) // enable HTTP/1
+	tr.Protocols.SetHTTP2(true) // enable HTTP/2
+}
+
+// To configure an [http.Server] to use HTTP/2,
+// set the [http.Server.Protocols] field.
+func ExampleConfigureServer() {
+	server := &http.Server{}
+	server.Protocols = new(http.Protocols)
+	server.Protocols.SetHTTP1(true) // enable HTTP/1
+	server.Protocols.SetHTTP2(true) // enable HTTP/2
+}
diff --git a/http2/server_common.go b/http2/server_common.go
index 449538c..fec3690 100644
--- a/http2/server_common.go
+++ b/http2/server_common.go
@@ -25,6 +25,8 @@
 //
 //	https://golang.org/pkg/net/http/#ResponseWriter
 //	https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
+//
+// Deprecated: Use [http.TrailerPrefix] instead.
 const TrailerPrefix = "Trailer:"
 
 // Push errors.
@@ -38,16 +40,22 @@
 // The configuration conf may be nil.
 //
 // ConfigureServer must be called before s begins serving.
+//
+// Deprecated: Set [http.Server.Protocols] instead.
 func ConfigureServer(s *http.Server, conf *Server) error {
 	return configureServer(s, conf)
 }
 
 // Server is an HTTP/2 server.
+//
+// Deprecated: Use [http.Server] instead.
 type Server struct {
 	// MaxHandlers limits the number of http.Handler ServeHTTP goroutines
 	// which may run at a time over all connections.
 	// Negative or zero no limit.
 	// TODO: implement
+	//
+	// Deprecated: This field has never had any effect.
 	MaxHandlers int
 
 	// MaxConcurrentStreams optionally specifies the number of
@@ -56,6 +64,9 @@
 	// which may be active globally, which is MaxHandlers.
 	// If zero, MaxConcurrentStreams defaults to at least 100, per
 	// the HTTP/2 spec's recommendations.
+	//
+	// Deprecated: Use [http.Server.HTTP2] and
+	// [http.HTTP2Config.MaxConcurrentStreams] instead.
 	MaxConcurrentStreams uint32
 
 	// MaxDecoderHeaderTableSize optionally specifies the http2
@@ -63,44 +74,67 @@
 	// 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.
+	//
+	// Deprecated: Use [http.Server.HTTP2] and
+	// [http.HTTP2Config.MaxDecoderHeaderTableSize] instead.
 	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.
+	//
+	// Deprecated: Use [http.Server.HTTP2] and
+	// [http.HTTP2Config.MaxEncoderHeaderTableSize] instead.
 	MaxEncoderHeaderTableSize uint32
 
 	// MaxReadFrameSize optionally specifies the largest frame
 	// this server is willing to read. A valid value is between
 	// 16k and 16M, inclusive. If zero or otherwise invalid, a
 	// default value is used.
+	//
+	// Deprecated: Use [http.Server.HTTP2] and
+	// [http.HTTP2Config.MaxReadFrameSize] instead.
 	MaxReadFrameSize uint32
 
 	// PermitProhibitedCipherSuites, if true, permits the use of
 	// cipher suites prohibited by the HTTP/2 spec.
+	//
+	// Deprecated: Use [http.Server.HTTP2] and
+	// [http.HTTP2Config.PermitProhibitedCipherSuites] instead.
 	PermitProhibitedCipherSuites bool
 
 	// IdleTimeout specifies how long until idle clients should be
 	// closed with a GOAWAY frame. PING frames are not considered
 	// activity for the purposes of IdleTimeout.
 	// If zero or negative, there is no timeout.
+	//
+	// Deprecated: Use [http.Server.IdleTimeout] instead.
 	IdleTimeout time.Duration
 
 	// ReadIdleTimeout 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.
+	//
+	// Deprecated: Use [http.Server.HTTP2] and
+	// [http.HTTP2Config.SendPingTimeout] instead.
 	ReadIdleTimeout 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.
+	//
+	// Deprecated: Use [http.Server.HTTP2] and
+	// [http.HTTP2Config.PingTimeout] instead.
 	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.
 	// If zero or negative, there is no timeout.
+	//
+	// Deprecated: Use [http.Server.HTTP2] and
+	// [http.HTTP2Config.WriteByteTimeout] instead.
 	WriteByteTimeout time.Duration
 
 	// MaxUploadBufferPerConnection is the size of the initial flow
@@ -108,12 +142,18 @@
 	// 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.
+	//
+	// Deprecated: Use [http.Server.HTTP2] and
+	// [http.HTTP2Config.MaxReceiveBufferPerConnection] 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.
+	//
+	// Deprecated: Use [http.Server.HTTP2] and
+	// [http.HTTP2Config.MaxReceiveBufferPerStream] instead.
 	MaxUploadBufferPerStream int32
 
 	// NewWriteScheduler constructs a write scheduler for a connection.
@@ -126,6 +166,9 @@
 	// It's intended to increment a metric for monitoring, such
 	// as an expvar or Prometheus metric.
 	// The errType consists of only ASCII word characters.
+	//
+	// Deprecated: Use [http.Server.HTTP2] and
+	// [http.HTTP2Config.CountError] instead.
 	CountError func(errType string)
 
 	// Internal state. This is a pointer (rather than embedded directly)
@@ -135,6 +178,8 @@
 }
 
 // ServeConnOpts are options for the Server.ServeConn method.
+//
+// Deprecated: ServeConnOpts is deprecated.
 type ServeConnOpts struct {
 	// Context is the base context to use.
 	// If nil, context.Background is used.
@@ -178,6 +223,8 @@
 // implemented in terms of providing a suitably-behaving net.Conn.
 //
 // The opts parameter is optional. If nil, default values are used.
+//
+// Deprecated: Use [http.Server.Serve] or [http.Server.ServeTLS] instead.
 func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
 	if opts == nil {
 		opts = &ServeConnOpts{}
diff --git a/http2/transport.go b/http2/transport.go
index 08ac409..088eb9b 100644
--- a/http2/transport.go
+++ b/http2/transport.go
@@ -184,6 +184,8 @@
 
 // ClientConn is the state of a single HTTP/2 client connection to an
 // HTTP/2 server.
+//
+// Deprecated: Use [http.ClientConn] instead.
 type ClientConn struct {
 	t             *Transport
 	tconn         net.Conn             // usually *tls.Conn, except specialized impls
diff --git a/http2/transport_common.go b/http2/transport_common.go
index b9f5293..ea3b25d 100644
--- a/http2/transport_common.go
+++ b/http2/transport_common.go
@@ -24,6 +24,8 @@
 // It returns an error if t1 has already been HTTP/2-enabled.
 //
 // Use ConfigureTransports instead to configure the HTTP/2 Transport.
+//
+// Deprecated: Set [http.Transport.Protocols] instead.
 func ConfigureTransport(t1 *http.Transport) error {
 	return configureTransport(t1)
 }
@@ -31,6 +33,8 @@
 // ConfigureTransports configures a net/http HTTP/1 Transport to use HTTP/2.
 // It returns a new HTTP/2 Transport for further configuration.
 // It returns an error if t1 has already been HTTP/2-enabled.
+//
+// Deprecated: Set [http.Transport.Protocols] instead.
 func ConfigureTransports(t1 *http.Transport) (*Transport, error) {
 	return configureTransports(t1)
 }
@@ -39,6 +43,8 @@
 //
 // A Transport internally caches connections to servers. It is safe
 // for concurrent use by multiple goroutines.
+//
+// Deprecated: Use [http.Transport] instead.
 type Transport struct {
 	// DialTLSContext specifies an optional dial function with context for
 	// creating TLS connections for requests.
@@ -47,6 +53,8 @@
 	//
 	// If the returned net.Conn has a ConnectionState method like tls.Conn,
 	// it will be used to set http.Response.TLS.
+	//
+	// Deprecated: Use [http.Transport.DialTLSContext] instead.
 	DialTLSContext func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error)
 
 	// DialTLS specifies an optional dial function for creating
@@ -54,17 +62,21 @@
 	//
 	// If DialTLSContext and DialTLS is nil, tls.Dial is used.
 	//
-	// Deprecated: Use DialTLSContext instead, which allows the transport
-	// to cancel dials as soon as they are no longer needed.
-	// If both are set, DialTLSContext takes priority.
+	// Deprecated: Use [http.Transport.DialTLSContext] instead.
 	DialTLS func(network, addr string, cfg *tls.Config) (net.Conn, error)
 
 	// TLSClientConfig specifies the TLS configuration to use with
 	// tls.Client. If nil, the default configuration is used.
+	//
+	// Deprecated: Use [http.Transport.TLSClientConfig] instead.
 	TLSClientConfig *tls.Config
 
 	// ConnPool optionally specifies an alternate connection pool to use.
 	// If nil, the default is used.
+	//
+	// Deprecated: To create a custom connection pool, implement
+	// [http.RoundTripper]. Use [http.Transport.NewClientConn]
+	// to create connections for the pool.
 	ConnPool ClientConnPool
 
 	// DisableCompression, if true, prevents the Transport from
@@ -75,10 +87,14 @@
 	// decoded in the Response.Body. However, if the user
 	// explicitly requested gzip it is not automatically
 	// uncompressed.
+	//
+	// Deprecated: Use [http.Transport.DisableCompression] instead.
 	DisableCompression bool
 
 	// AllowHTTP, if true, permits HTTP/2 requests using the insecure,
 	// plain-text "http" scheme. Note that this does not enable h2c support.
+	//
+	// Deprecated: Use [http.Transport.Protocols] instead.
 	AllowHTTP bool
 
 	// MaxHeaderListSize is the http2 SETTINGS_MAX_HEADER_LIST_SIZE to
@@ -88,6 +104,8 @@
 	// want to advertise an unlimited value to the peer, Transport
 	// interprets the highest possible value here (0xffffffff or 1<<32-1)
 	// to mean no limit.
+	//
+	// Deprecated: Use [http.Transport.MaxResponseHeaderBytes] instead.
 	MaxHeaderListSize uint32
 
 	// MaxReadFrameSize is the http2 SETTINGS_MAX_FRAME_SIZE to send in the
@@ -97,6 +115,9 @@
 	// according to the spec:
 	// https://datatracker.ietf.org/doc/html/rfc7540#section-6.5.2.
 	// Values are bounded in the range 16k to 16M.
+	//
+	// Deprecated: Use [http.Transport.HTTP2] and
+	// [http.HTTP2Config.MaxReadFrameSize] instead.
 	MaxReadFrameSize uint32
 
 	// MaxDecoderHeaderTableSize optionally specifies the http2
@@ -104,12 +125,18 @@
 	// 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.
+	//
+	// Deprecated: Use [http.Transport.HTTP2] and
+	// [http.HTTP2Config.MaxDecoderHeaderTableSize] instead.
 	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.
+	//
+	// Deprecated: Use [http.Transport.HTTP2] and
+	// [http.HTTP2Config.MaxEncoderHeaderTableSize] instead.
 	MaxEncoderHeaderTableSize uint32
 
 	// StrictMaxConcurrentStreams controls whether the server's
@@ -120,12 +147,17 @@
 	// server's SETTINGS_MAX_CONCURRENT_STREAMS is interpreted as
 	// a global limit and callers of RoundTrip block when needed,
 	// waiting for their turn.
+	//
+	// Deprecated: Use [http.Transport.HTTP2] and
+	// [http.HTTP2Config.StrictMaxConcurrentRequests] instead.
 	StrictMaxConcurrentStreams bool
 
 	// IdleConnTimeout is the maximum amount of time an idle
 	// (keep-alive) connection will remain idle before closing
 	// itself.
 	// Zero means no limit.
+	//
+	// Deprecated: Use [http.Transport.IdleConnTimeout] instead.
 	IdleConnTimeout time.Duration
 
 	// ReadIdleTimeout is the timeout after which a health check using ping
@@ -134,22 +166,34 @@
 	// there is no other traffic on the connection, the health check will
 	// be performed every ReadIdleTimeout interval.
 	// If zero, no health check is performed.
+	//
+	// Deprecated: Use [http.Transport.HTTP2] and
+	// [http.HTTP2Config.SendPingTimeout] instead.
 	ReadIdleTimeout time.Duration
 
 	// PingTimeout is the timeout after which the connection will be closed
 	// if a response to Ping is not received.
 	// Defaults to 15s.
+	//
+	// Deprecated: Use [http.Transport.HTTP2] and
+	// [http.HTTP2Config.PingTimeout] instead.
 	PingTimeout time.Duration
 
 	// WriteByteTimeout is the timeout after which the connection will be
 	// closed no data can be written to it. The timeout begins when data is
 	// available to write, and is extended whenever any bytes are written.
+	//
+	// Deprecated: Use [http.Transport.HTTP2] and
+	// [http.HTTP2Config.WriteByteTimeout] instead.
 	WriteByteTimeout time.Duration
 
 	// CountError, if non-nil, is called on HTTP/2 transport 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.
+	//
+	// Deprecated: Use [http.Transport.HTTP2] and
+	// [http.HTTP2Config.CountError] instead.
 	CountError func(errType string)
 
 	// Internal state, differs between wrapped and non-wrapped implementations.
@@ -165,6 +209,10 @@
 )
 
 // ClientConnPool manages a pool of HTTP/2 client connections.
+//
+// Deprecated: To create a custom connection pool, implement
+// [http.RoundTripper]. Use [http.Transport.NewClientConn]
+// to create connections for the pool.
 type ClientConnPool interface {
 	// GetClientConn returns a specific HTTP/2 connection (usually
 	// a TLS-TCP connection) to an HTTP/2 server. On success, the
@@ -177,6 +225,8 @@
 }
 
 // ClientConnState describes the state of a ClientConn.
+//
+// Deprecated: Use [http.ClientConn] instead.
 type ClientConnState struct {
 	// Closed is whether the connection is closed.
 	Closed bool
@@ -210,6 +260,8 @@
 }
 
 // RoundTripOpt are options for the Transport.RoundTripOpt method.
+//
+// Deprecated: There are no options to set.
 type RoundTripOpt struct {
 	// OnlyCachedConn controls whether RoundTripOpt may
 	// create a new TCP connection. If set true and
@@ -222,11 +274,14 @@
 	allowHTTP bool // allow http:// URLs
 }
 
+// Deprecated: Use [http.Transport.RoundTrip] instead.
 func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
 	return t.RoundTripOpt(req, RoundTripOpt{})
 }
 
 // RoundTripOpt is like RoundTrip, but takes options.
+//
+// Deprecated: Use [http.Transport.RoundTrip] instead.
 func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Response, error) {
 	return t.roundTripOpt(req, opt)
 }
@@ -234,10 +289,15 @@
 // CloseIdleConnections closes any connections which were previously
 // connected from previous requests but are now sitting idle.
 // It does not interrupt any connections currently in use.
+//
+// Deprecated: Use [http.Transport.CloseIdleConnections] instead.
 func (t *Transport) CloseIdleConnections() {
 	t.closeIdleConnections()
 }
 
+// NewClientConn is deprecated.
+//
+// Deprecated: Use [http.Transport.NewClientConn] instead.
 func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) {
 	return t.newUserClientConn(c)
 }
@@ -414,6 +474,8 @@
 
 // GoAwayError is returned by the Transport when the server closes the
 // TCP connection after sending a GOAWAY frame.
+//
+// Deprecated: GoAwayError is deprecated.
 type GoAwayError struct {
 	LastStreamID uint32
 	ErrCode      ErrCode
diff --git a/http2/transport_wrap.go b/http2/transport_wrap.go
index 741fb97..34dfb3c 100644
--- a/http2/transport_wrap.go
+++ b/http2/transport_wrap.go
@@ -216,6 +216,8 @@
 
 // ClientConn is the state of a single HTTP/2 client connection to an
 // HTTP/2 server.
+//
+// Deprecated: Use [http.ClientConn] instead.
 type ClientConn struct {
 	cc         *http.ClientConn
 	tconn      net.Conn