Dialing HTTP/3
This package provides a http.RoundTripper
implementation that can be used on the http.Client
:
tr := &http3.Transport{
TLSClientConfig: &tls.Config{}, // set a TLS client config, if desired
QUICConfig: &quic.Config{}, // QUIC connection options
}
defer tr.Close()
client := &http.Client{
Transport: tr,
}
The http.Client
can then be used to perform HTTP requests over HTTP/3.
Using a quic.Transport
To use a custom quic.Transport
, the function used to dial new QUIC connections can be configured:
tr := quic.Transport{}
h3tr := &http3.Transport{
TLSClientConfig: &tls.Config{}, // set a TLS client config, if desired
QUICConfig: &quic.Config{}, // QUIC connection options
Dial: func(ctx context.Context, addr string, tlsConf *tls.Config, quicConf *quic.Config) (quic.EarlyConnection, error) {
a, err := net.ResolveUDPAddr("udp", addr)
if err != nil {
return nil, err
}
return tr.DialEarly(ctx, a, tlsConf, quicConf)
},
}
This gives the application more fine-grained control over the configuration of the quic.Transport
.
Running Client and Server on the Same Socket
Since QUIC demultiplexes packets based on their connection IDs, it is possible allows running a QUIC server and client on the same UDP socket. This also works when using HTTP/3: HTTP requests can be sent from the same socket that a server is listening on.
To achieve this using this package, first initialize a single quic.Transport
, and pass a quic.EarlyListner
obtained from that transport to http3.Server.ServeListener
, and use the DialEarly
function of the transport as the Dial
function for the http3.Transport
.
Using 0-RTT
The use of 0-RTT was not anticipated by Go’s standard library, and Go doesn’t have 0-RTT support, neither in its crypto/tls
nor in its net/http
implementation (not even for TLS 1.3 on top of TCP). The http3
package therefore defines two new request methods: http3.MethodGet0RTT
for GET requests and http3.MethodHead0RTT
for HEAD requests.
It is the application’s responsibility to make sure that it is actually safe to send a request in 0-RTT, as outlined in Security Properties of 0-RTT. Requests sent in 0-RTT can be replayed on a new connection by an on-path attacker, so 0-RTT should only be used for idempotent requests. RFC 8740 defines some guidance on how to use 0-RTT in HTTP.
tr := &http3.Transport{
TLSClientConfig: &tls.Config{
ClientSessionCache: tls.NewLRUClientSessionCache(100),
},
}
req, err := http.NewRequest(http3.MethodGet0RTT, "https://my-server/path", nil)
// ... handle error ...
tr.RoundTrip(req)
The code snippet shows all the knobs that need to be turned to send a request in 0-RTT data:
- TLS session resumption must be enabled by configuring a
tls.ClientSessionCache
on thetls.Config
. - The request method needs to be set to
http3.MethodGet0RTT
.