@marcel91200 / caddy Mirror · read-only / commits / 5f6758da
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 12, 12:00 UTC

reverseproxy: Support HTTP/3 transport to backend (#6312)

Closes #5086

Matt Holt committed May 20, 2024 at 13:06 UTC 5f6758dab5fc02f74233a92c53ba3b654e476dc0
1 file changed +22
modules/caddyhttp/reverseproxy/httptransport.go
+22
@@ -31,6 +31,7 @@ import (
31 "time"
32
33 "github.com/pires/go-proxyproto"
34 + "github.com/quic-go/quic-go/http3"
35 "go.uber.org/zap"
36 "golang.org/x/net/http2"
37
@@ -124,12 +125,18 @@ type HTTPTransport struct {
125 // can be specified to use H2C (HTTP/2 over Cleartext) to the
126 // upstream (this feature is experimental and subject to
127 // change or removal). Default: ["1.1", "2"]
128 + //
129 + // EXPERIMENTAL: "3" enables HTTP/3, but it must be the only
130 + // version specified if enabled. Additionally, HTTPS must be
131 + // enabled to the upstream as HTTP/3 requires TLS. Subject
132 + // to change or removal while experimental.
133 Versions []string `json:"versions,omitempty"`
134
135 // The pre-configured underlying HTTP transport.
136 Transport *http.Transport `json:"-"`
137
138 h2cTransport *http2.Transport
139 + h3Transport *http3.RoundTripper // TODO: EXPERIMENTAL (May 2024)
140 }
141
142 // CaddyModule returns the Caddy module information.
@@ -350,6 +357,16 @@ func (h *HTTPTransport) NewTransport(caddyCtx caddy.Context) (*http.Transport, e
357 }
358 }
359
360 + // configure HTTP/3 transport if enabled; however, this does not
361 + // automatically fall back to lower versions like most web browsers
362 + // do (that'd add latency and complexity, besides, we expect that
363 + // site owners control the backends), so it must be exclusive
364 + if len(h.Versions) == 1 && h.Versions[0] == "3" {
365 + h.h3Transport = new(http3.RoundTripper)
366 + } else if len(h.Versions) > 1 && sliceContains(h.Versions, "3") {
367 + return nil, fmt.Errorf("if HTTP/3 is enabled to the upstream, no other HTTP versions are supported")
368 + }
369 +
370 // if h2c is enabled, configure its transport (std lib http.Transport
371 // does not "HTTP/2 over cleartext TCP")
372 if sliceContains(h.Versions, "h2c") {
@@ -414,6 +431,11 @@ func (h *HTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) {
431
432 transport.SetScheme(req)
433
434 + // use HTTP/3 if enabled (TODO: This is EXPERIMENTAL)
435 + if h.h3Transport != nil {
436 + return h.h3Transport.RoundTrip(req)
437 + }
438 +
439 // if H2C ("HTTP/2 over cleartext") is enabled and the upstream request is
440 // HTTP without TLS, use the alternate H2C-capable transport instead
441 if req.URL.Scheme == "http" && h.h2cTransport != nil {