mirror of
https://github.com/golang/go.git
synced 2026-04-04 02:10:08 +09:00
net/http: add pluggable HTTP/3 support for closing idle connections
This CL defines the closeIdleConectionser interface, allowing us to call a CloseIdleConnections method that a pluggable HTTP/3 transport might implement. Concretely, this allows an HTTP/3 transport implementation to clean up resources such as an open UDP socket that is no longer needed, preventing resources from lingering around indefinitely until the entire program exits. For #77440 Change-Id: I7216caee58954c3651f96a56dbf27ec74c539ad3 Reviewed-on: https://go-review.googlesource.com/c/go/+/753161 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Nicholas Husin <husin@google.com> Reviewed-by: Damien Neil <dneil@google.com>
This commit is contained in:
committed by
Nicholas Husin
parent
e30e65f7a8
commit
96d6d38872
@@ -388,9 +388,8 @@ type dialClientConner interface {
|
||||
// If HTTP/3 proxies are not supported, DialClientConn should return
|
||||
// an error wrapping [errors.ErrUnsupported].
|
||||
//
|
||||
// The RoundTripper returned by DialClientConn may implement
|
||||
// any of the following methods to support the [ClientConn]
|
||||
// method of the same name:
|
||||
// The RoundTripper returned by DialClientConn must also implement the
|
||||
// following methods to support [ClientConn] methods of the same name:
|
||||
// Close() error
|
||||
// Err() error
|
||||
// Reserve() error
|
||||
@@ -411,6 +410,16 @@ type dialClientConner interface {
|
||||
DialClientConn(ctx context.Context, address string, proxy *url.URL, internalStateHook func()) (RoundTripper, error)
|
||||
}
|
||||
|
||||
type closeIdleConnectionser interface {
|
||||
// CloseIdleConnections is called by Transport.CloseIdleConnections.
|
||||
//
|
||||
// The transport will close idle connections created with DialClientConn
|
||||
// before calling this method. The HTTP/3 transport should not attempt to
|
||||
// close idle connections, but may clean up shared resources such as UDP
|
||||
// sockets if no connections remain.
|
||||
CloseIdleConnections()
|
||||
}
|
||||
|
||||
// h2Transport is the interface we expect to be able to call from
|
||||
// net/http against an *http2.Transport that's either bundled into
|
||||
// h2_bundle.go or supplied by the user via x/net/http2.
|
||||
@@ -956,6 +965,9 @@ func (t *Transport) CloseIdleConnections() {
|
||||
if t2 := t.h2transport; t2 != nil {
|
||||
t2.CloseIdleConnections()
|
||||
}
|
||||
if cc, ok := t.h3transport.(closeIdleConnectionser); ok {
|
||||
cc.CloseIdleConnections()
|
||||
}
|
||||
}
|
||||
|
||||
// prepareTransportCancel sets up state to convert Transport.CancelRequest into context cancelation.
|
||||
@@ -3088,11 +3100,16 @@ func (pc *persistConn) closeLocked(err error) {
|
||||
pc.t.decConnsPerHost(pc.cacheKey)
|
||||
// Close HTTP/1 (pc.alt == nil) connection.
|
||||
// HTTP/2 closes its connection itself.
|
||||
// Close HTTP/3 connection if it implements io.Closer.
|
||||
if pc.alt == nil {
|
||||
if err != errCallerOwnsConn {
|
||||
pc.conn.Close()
|
||||
}
|
||||
close(pc.closech)
|
||||
} else {
|
||||
if cc, ok := pc.alt.(io.Closer); ok {
|
||||
cc.Close()
|
||||
}
|
||||
}
|
||||
}
|
||||
pc.mutateHeaderFunc = nil
|
||||
|
||||
Reference in New Issue
Block a user