diff --git a/http3/client.go b/http3/client.go index ae08f44d..b8378c6f 100644 --- a/http3/client.go +++ b/http3/client.go @@ -37,6 +37,7 @@ var dialAddr = quic.DialAddrEarly type roundTripperOpts struct { DisableCompression bool + EnableDatagram bool MaxHeaderBytes int64 } @@ -68,7 +69,7 @@ func newClient( dialer func(network, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlySession, error), ) (*client, error) { if quicConfig == nil { - quicConfig = defaultQuicConfig + quicConfig = defaultQuicConfig.Clone() } else if len(quicConfig.Versions) == 0 { quicConfig = quicConfig.Clone() quicConfig.Versions = []quic.VersionNumber{defaultQuicConfig.Versions[0]} @@ -77,6 +78,7 @@ func newClient( return nil, errors.New("can only use a single QUIC version for dialing a HTTP/3 connection") } quicConfig.MaxIncomingStreams = -1 // don't allow any bidirectional streams + quicConfig.EnableDatagrams = opts.EnableDatagram logger := utils.DefaultLogger.WithPrefix("h3 client") if tlsConf == nil { @@ -131,7 +133,7 @@ func (c *client) setupSession() error { buf := &bytes.Buffer{} utils.WriteVarInt(buf, streamTypeControlStream) // send the SETTINGS frame - (&settingsFrame{}).Write(buf) + (&settingsFrame{Datagram: c.opts.EnableDatagram}).Write(buf) _, err = str.Write(buf.Bytes()) return err } diff --git a/http3/client_test.go b/http3/client_test.go index 2708d161..5d5733e2 100644 --- a/http3/client_test.go +++ b/http3/client_test.go @@ -136,6 +136,18 @@ var _ = Describe("Client", func() { Expect(dialerCalled).To(BeTrue()) }) + It("enables HTTP/3 Datagrams", func() { + testErr := errors.New("handshake error") + client, err := newClient("localhost:1337", nil, &roundTripperOpts{EnableDatagram: true}, nil, nil) + Expect(err).ToNot(HaveOccurred()) + dialAddr = func(hostname string, _ *tls.Config, quicConf *quic.Config) (quic.EarlySession, error) { + Expect(quicConf.EnableDatagrams).To(BeTrue()) + return nil, testErr + } + _, err = client.RoundTrip(req) + Expect(err).To(MatchError(testErr)) + }) + It("errors when dialing fails", func() { testErr := errors.New("handshake error") client, err := newClient("localhost:1337", nil, &roundTripperOpts{}, nil, nil) diff --git a/http3/roundtrip.go b/http3/roundtrip.go index 3b074d32..264ed63f 100644 --- a/http3/roundtrip.go +++ b/http3/roundtrip.go @@ -41,6 +41,11 @@ type RoundTripper struct { // If nil, reasonable default values will be used. QuicConfig *quic.Config + // Enable support for HTTP/3 datagrams. + // If set to true, QuicConfig.EnableDatagram will be set. + // See https://www.ietf.org/archive/id/draft-schinazi-masque-h3-datagram-02.html. + EnableDatagrams bool + // Dial specifies an optional dial function for creating QUIC // connections for requests. // If Dial is nil, quic.DialAddr will be used. @@ -135,6 +140,7 @@ func (r *RoundTripper) getClient(hostname string, onlyCached bool) (http.RoundTr hostname, r.TLSClientConfig, &roundTripperOpts{ + EnableDatagram: r.EnableDatagrams, DisableCompression: r.DisableCompression, MaxHeaderBytes: r.MaxResponseHeaderBytes, },