diff --git a/http3/client.go b/http3/client.go index feb14cbc6..9121d116d 100644 --- a/http3/client.go +++ b/http3/client.go @@ -115,6 +115,7 @@ func newClientConn( return c } +// OpenRequestStream opens a new request stream on the HTTP/3 connection. func (c *ClientConn) OpenRequestStream(ctx context.Context) (RequestStream, error) { return c.connection.openRequestStream(ctx, c.requestWriter, nil, c.disableCompression, c.maxResponseHeaderBytes) } diff --git a/http3/conn.go b/http3/conn.go index 2b5b9a822..ec62ed3f5 100644 --- a/http3/conn.go +++ b/http3/conn.go @@ -316,10 +316,12 @@ func (c *connection) receiveDatagrams() error { } // ReceivedSettings returns a channel that is closed once the peer's SETTINGS frame was received. +// Settings can be optained from the Settings method after the channel was closed. func (c *connection) ReceivedSettings() <-chan struct{} { return c.receivedSettings } // Settings returns the settings received on this connection. // It is only valid to call this function after the channel returned by ReceivedSettings was closed. func (c *connection) Settings() *Settings { return c.settings } +// Context returns the context of the underlying QUIC connection. func (c *connection) Context() context.Context { return c.ctx } diff --git a/http3/transport.go b/http3/transport.go index 52444c60e..c47b5484d 100644 --- a/http3/transport.go +++ b/http3/transport.go @@ -62,8 +62,6 @@ func (r *roundTripperWithCount) Close() error { // Transport implements the http.RoundTripper interface type Transport struct { - mutex sync.Mutex - // TLSClientConfig specifies the TLS configuration to use with // tls.Client. If nil, the default configuration is used. TLSClientConfig *tls.Config @@ -103,6 +101,8 @@ type Transport struct { Logger *slog.Logger + mutex sync.Mutex + initOnce sync.Once initErr error @@ -334,6 +334,12 @@ func (t *Transport) removeClient(hostname string) { delete(t.clients, hostname) } +// NewClientConn creates a new HTTP/3 client connection on top of a QUIC connection. +// Most users should use RoundTrip instead of creating a connection directly. +// Specifically, it is not needed to perform GET, POST, HEAD and CONNECT requests. +// +// Obtaining a ClientConn is only needed for more advanced use cases, such as +// using Extended CONNECT for WebTransport or the various MASQUE protocols. func (t *Transport) NewClientConn(conn quic.Connection) *ClientConn { return newClientConn( conn, @@ -348,7 +354,6 @@ func (t *Transport) NewClientConn(conn quic.Connection) *ClientConn { } // Close closes the QUIC connections that this Transport has used. -// It also closes the underlying UDPConn if it is not nil. func (t *Transport) Close() error { t.mutex.Lock() defer t.mutex.Unlock() @@ -398,6 +403,10 @@ func isNotToken(r rune) bool { return !httpguts.IsTokenRune(r) } +// CloseIdleConnections closes any QUIC connections in the transport's pool that are currently idle. +// An idle connection is one that was previously used for requests but is now sitting unused. +// This method does not interrupt any connections currently in use. +// It also does not affect connections obtained via NewClientConn. func (t *Transport) CloseIdleConnections() { t.mutex.Lock() defer t.mutex.Unlock()