summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Holt <mholt@users.noreply.github.com>2024-05-20 13:06:43 -0600
committerGitHub <noreply@github.com>2024-05-20 13:06:43 -0600
commit5f6758dab5fc02f74233a92c53ba3b654e476dc0 (patch)
treec574171fd973d699d24ad3dc44420e5cec2daae1
parenta6a45ff6c56d2d0df1ac86f22d38997da3ba3b39 (diff)
reverseproxy: Support HTTP/3 transport to backend (#6312)
Closes #5086
-rw-r--r--modules/caddyhttp/reverseproxy/httptransport.go22
1 files changed, 22 insertions, 0 deletions
diff --git a/modules/caddyhttp/reverseproxy/httptransport.go b/modules/caddyhttp/reverseproxy/httptransport.go
index f52a0805..80a49806 100644
--- a/modules/caddyhttp/reverseproxy/httptransport.go
+++ b/modules/caddyhttp/reverseproxy/httptransport.go
@@ -31,6 +31,7 @@ import (
"time"
"github.com/pires/go-proxyproto"
+ "github.com/quic-go/quic-go/http3"
"go.uber.org/zap"
"golang.org/x/net/http2"
@@ -124,12 +125,18 @@ type HTTPTransport struct {
// can be specified to use H2C (HTTP/2 over Cleartext) to the
// upstream (this feature is experimental and subject to
// change or removal). Default: ["1.1", "2"]
+ //
+ // EXPERIMENTAL: "3" enables HTTP/3, but it must be the only
+ // version specified if enabled. Additionally, HTTPS must be
+ // enabled to the upstream as HTTP/3 requires TLS. Subject
+ // to change or removal while experimental.
Versions []string `json:"versions,omitempty"`
// The pre-configured underlying HTTP transport.
Transport *http.Transport `json:"-"`
h2cTransport *http2.Transport
+ h3Transport *http3.RoundTripper // TODO: EXPERIMENTAL (May 2024)
}
// CaddyModule returns the Caddy module information.
@@ -350,6 +357,16 @@ func (h *HTTPTransport) NewTransport(caddyCtx caddy.Context) (*http.Transport, e
}
}
+ // configure HTTP/3 transport if enabled; however, this does not
+ // automatically fall back to lower versions like most web browsers
+ // do (that'd add latency and complexity, besides, we expect that
+ // site owners control the backends), so it must be exclusive
+ if len(h.Versions) == 1 && h.Versions[0] == "3" {
+ h.h3Transport = new(http3.RoundTripper)
+ } else if len(h.Versions) > 1 && sliceContains(h.Versions, "3") {
+ return nil, fmt.Errorf("if HTTP/3 is enabled to the upstream, no other HTTP versions are supported")
+ }
+
// if h2c is enabled, configure its transport (std lib http.Transport
// does not "HTTP/2 over cleartext TCP")
if sliceContains(h.Versions, "h2c") {
@@ -414,6 +431,11 @@ func (h *HTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) {
transport.SetScheme(req)
+ // use HTTP/3 if enabled (TODO: This is EXPERIMENTAL)
+ if h.h3Transport != nil {
+ return h.h3Transport.RoundTrip(req)
+ }
+
// if H2C ("HTTP/2 over cleartext") is enabled and the upstream request is
// HTTP without TLS, use the alternate H2C-capable transport instead
if req.URL.Scheme == "http" && h.h2cTransport != nil {