http3: improve the client API (#4693)

* http3: rename RoundTripper to Transport

* http3: rename SingleDestinationRoundTripper to ClientConn

* http3: construct the ClientConn via Transport.NewClientConn
This commit is contained in:
Marten Seemann
2024-10-14 00:17:50 -05:00
committed by GitHub
parent eaa879f32f
commit 1db805ce4f
8 changed files with 389 additions and 324 deletions

View File

@@ -64,7 +64,7 @@ var _ = Describe("HTTP3 Server hotswap test", func() {
mux1 *http.ServeMux
mux2 *http.ServeMux
client *http.Client
rt *http3.RoundTripper
rt *http3.Transport
server1 *http3.Server
server2 *http3.Server
ln *listenerWrapper
@@ -106,7 +106,7 @@ var _ = Describe("HTTP3 Server hotswap test", func() {
})
BeforeEach(func() {
rt = &http3.RoundTripper{
rt = &http3.Transport{
TLSClientConfig: getTLSClientConfig(),
DisableCompression: true,
QUICConfig: getQuicConfig(&quic.Config{MaxIdleTimeout: 10 * time.Second}),
@@ -151,7 +151,7 @@ var _ = Describe("HTTP3 Server hotswap test", func() {
Expect(fake1.closed.Load()).To(BeTrue())
Expect(fake2.closed.Load()).To(BeFalse())
Expect(ln.listenerClosed).ToNot(BeTrue())
Expect(client.Transport.(*http3.RoundTripper).Close()).NotTo(HaveOccurred())
Expect(client.Transport.(*http3.Transport).Close()).NotTo(HaveOccurred())
// verify that new connections are being initiated from the second server now
resp, err = client.Get("https://localhost:" + port + "/hello2")

View File

@@ -46,7 +46,7 @@ var _ = Describe("HTTP tests", func() {
var (
mux *http.ServeMux
client *http.Client
rt *http3.RoundTripper
tr *http3.Transport
server *http3.Server
stoppedServing chan struct{}
port int
@@ -112,20 +112,20 @@ var _ = Describe("HTTP tests", func() {
})
AfterEach(func() {
Expect(rt.Close()).NotTo(HaveOccurred())
Expect(tr.Close()).NotTo(HaveOccurred())
Expect(server.Close()).NotTo(HaveOccurred())
Eventually(stoppedServing).Should(BeClosed())
})
BeforeEach(func() {
rt = &http3.RoundTripper{
tr = &http3.Transport{
TLSClientConfig: getTLSClientConfigWithoutServerName(),
QUICConfig: getQuicConfig(&quic.Config{
MaxIdleTimeout: 10 * time.Second,
}),
DisableCompression: true,
}
client = &http.Client{Transport: rt}
client = &http.Client{Transport: tr}
})
It("closes the connection after idle timeout", func() {
@@ -166,7 +166,7 @@ var _ = Describe("HTTP tests", func() {
var dialCounter int
testErr := errors.New("test error")
cl := http.Client{
Transport: &http3.RoundTripper{
Transport: &http3.Transport{
TLSClientConfig: getTLSClientConfig(),
Dial: func(ctx context.Context, addr string, tlsConf *tls.Config, conf *quic.Config) (quic.EarlyConnection, error) {
dialCounter++
@@ -355,7 +355,7 @@ var _ = Describe("HTTP tests", func() {
gw.Write([]byte("Hello, World!\n"))
})
client.Transport.(*http3.RoundTripper).DisableCompression = false
client.Transport.(*http3.Transport).DisableCompression = false
resp, err := client.Get(fmt.Sprintf("https://localhost:%d/gzipped/hello", port))
Expect(err).ToNot(HaveOccurred())
Expect(resp.StatusCode).To(Equal(200))
@@ -484,8 +484,9 @@ var _ = Describe("HTTP tests", func() {
)
Expect(err).ToNot(HaveOccurred())
defer conn.CloseWithError(0, "")
rt := http3.SingleDestinationRoundTripper{Connection: conn}
str, err := rt.OpenRequestStream(context.Background())
tr := http3.Transport{}
cc := tr.NewClientConn(conn)
str, err := cc.OpenRequestStream(context.Background())
Expect(err).ToNot(HaveOccurred())
Expect(str.SendRequestHeader(req)).To(Succeed())
// make sure the request is received (and not stuck in some buffer, for example)
@@ -677,10 +678,10 @@ var _ = Describe("HTTP tests", func() {
)
Expect(err).ToNot(HaveOccurred())
defer conn.CloseWithError(0, "")
rt := http3.SingleDestinationRoundTripper{Connection: conn}
hconn := rt.Start()
Eventually(hconn.ReceivedSettings(), 5*time.Second, 10*time.Millisecond).Should(BeClosed())
settings := hconn.Settings()
var tr http3.Transport
cc := tr.NewClientConn(conn)
Eventually(cc.ReceivedSettings(), 5*time.Second, 10*time.Millisecond).Should(BeClosed())
settings := cc.Settings()
Expect(settings.EnableExtendedConnect).To(BeTrue())
Expect(settings.EnableDatagrams).To(BeFalse())
Expect(settings.Other).To(BeEmpty())
@@ -696,7 +697,7 @@ var _ = Describe("HTTP tests", func() {
w.WriteHeader(http.StatusOK)
})
rt = &http3.RoundTripper{
tr = &http3.Transport{
TLSClientConfig: getTLSClientConfigWithoutServerName(),
QUICConfig: getQuicConfig(&quic.Config{
MaxIdleTimeout: 10 * time.Second,
@@ -708,7 +709,7 @@ var _ = Describe("HTTP tests", func() {
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("https://localhost:%d/settings", port), nil)
Expect(err).ToNot(HaveOccurred())
_, err = rt.RoundTrip(req)
_, err = tr.RoundTrip(req)
Expect(err).ToNot(HaveOccurred())
var settings *http3.Settings
Expect(settingsChan).To(Receive(&settings))
@@ -803,11 +804,9 @@ var _ = Describe("HTTP tests", func() {
)
Expect(err).ToNot(HaveOccurred())
rt := &http3.SingleDestinationRoundTripper{
Connection: conn,
EnableDatagrams: true,
}
str, err := rt.OpenRequestStream(context.Background())
tr := http3.Transport{EnableDatagrams: true}
cc := tr.NewClientConn(conn)
str, err := cc.OpenRequestStream(context.Background())
Expect(err).ToNot(HaveOccurred())
u, err := url.Parse(h)
Expect(err).ToNot(HaveOccurred())
@@ -981,21 +980,21 @@ var _ = Describe("HTTP tests", func() {
tlsConf := getTLSClientConfigWithoutServerName()
puts := make(chan string, 10)
tlsConf.ClientSessionCache = newClientSessionCache(tls.NewLRUClientSessionCache(10), nil, puts)
rt := &http3.RoundTripper{
tr := &http3.Transport{
TLSClientConfig: tlsConf,
QUICConfig: getQuicConfig(&quic.Config{
MaxIdleTimeout: 10 * time.Second,
}),
DisableCompression: true,
}
defer rt.Close()
defer tr.Close()
mux.HandleFunc("/0rtt", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(strconv.FormatBool(!r.TLS.HandshakeComplete)))
})
req, err := http.NewRequest(http3.MethodGet0RTT, fmt.Sprintf("https://localhost:%d/0rtt", proxy.LocalPort()), nil)
Expect(err).ToNot(HaveOccurred())
rsp, err := rt.RoundTrip(req)
rsp, err := tr.RoundTrip(req)
Expect(err).ToNot(HaveOccurred())
Expect(rsp.StatusCode).To(BeEquivalentTo(200))
data, err := io.ReadAll(rsp.Body)
@@ -1004,13 +1003,13 @@ var _ = Describe("HTTP tests", func() {
Expect(num0RTTPackets.Load()).To(BeZero())
Eventually(puts).Should(Receive())
rt2 := &http3.RoundTripper{
TLSClientConfig: rt.TLSClientConfig,
QUICConfig: rt.QUICConfig,
tr2 := &http3.Transport{
TLSClientConfig: tr.TLSClientConfig,
QUICConfig: tr.QUICConfig,
DisableCompression: true,
}
defer rt2.Close()
rsp, err = rt2.RoundTrip(req)
defer tr2.Close()
rsp, err = tr2.RoundTrip(req)
Expect(err).ToNot(HaveOccurred())
Expect(rsp.StatusCode).To(BeEquivalentTo(200))
data, err = io.ReadAll(rsp.Body)
@@ -1111,7 +1110,7 @@ var _ = Describe("HTTP tests", func() {
Expect(err).ToNot(HaveOccurred())
Expect(body).To(Equal([]byte("shutdown")))
// manually close the client, since we don't support
client.Transport.(*http3.RoundTripper).Close()
client.Transport.(*http3.Transport).Close()
// make sure that CloseGracefully returned
Eventually(done).Should(BeClosed())