Skip to content

Commit 1e21b66

Browse files
authored
reverseproxy: use http.Protocols to handle h2c requests (#6990)
1 parent 595aab8 commit 1e21b66

1 file changed

Lines changed: 15 additions & 34 deletions

File tree

modules/caddyhttp/reverseproxy/httptransport.go

Lines changed: 15 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,7 @@ type HTTPTransport struct {
160160
// `HTTPS_PROXY`, and `NO_PROXY` environment variables.
161161
NetworkProxyRaw json.RawMessage `json:"network_proxy,omitempty" caddy:"namespace=caddy.network_proxy inline_key=from"`
162162

163-
h2cTransport *http2.Transport
164-
h3Transport *http3.Transport // TODO: EXPERIMENTAL (May 2024)
163+
h3Transport *http3.Transport // TODO: EXPERIMENTAL (May 2024)
165164
}
166165

167166
// CaddyModule returns the Caddy module information.
@@ -472,12 +471,6 @@ func (h *HTTPTransport) NewTransport(caddyCtx caddy.Context) (*http.Transport, e
472471
rt.DisableCompression = !*h.Compression
473472
}
474473

475-
if slices.Contains(h.Versions, "2") {
476-
if err := http2.ConfigureTransport(rt); err != nil {
477-
return nil, err
478-
}
479-
}
480-
481474
// configure HTTP/3 transport if enabled; however, this does not
482475
// automatically fall back to lower versions like most web browsers
483476
// do (that'd add latency and complexity, besides, we expect that
@@ -495,25 +488,22 @@ func (h *HTTPTransport) NewTransport(caddyCtx caddy.Context) (*http.Transport, e
495488
return nil, fmt.Errorf("if HTTP/3 is enabled to the upstream, no other HTTP versions are supported")
496489
}
497490

498-
// if h2c is enabled, configure its transport (std lib http.Transport
499-
// does not "HTTP/2 over cleartext TCP")
500-
if slices.Contains(h.Versions, "h2c") {
501-
// crafting our own http2.Transport doesn't allow us to utilize
502-
// most of the customizations/preferences on the http.Transport,
503-
// because, for some reason, only http2.ConfigureTransport()
504-
// is allowed to set the unexported field that refers to a base
505-
// http.Transport config; oh well
506-
h2t := &http2.Transport{
507-
// kind of a hack, but for plaintext/H2C requests, pretend to dial TLS
508-
DialTLSContext: func(ctx context.Context, network, address string, _ *tls.Config) (net.Conn, error) {
509-
return dialContext(ctx, network, address)
510-
},
511-
AllowHTTP: true,
491+
// if h2/c is enabled, configure it explicitly
492+
if slices.Contains(h.Versions, "2") || slices.Contains(h.Versions, "h2c") {
493+
if err := http2.ConfigureTransport(rt); err != nil {
494+
return nil, err
512495
}
513-
if h.Compression != nil {
514-
h2t.DisableCompression = !*h.Compression
496+
497+
// DisableCompression from h2 is configured by http2.ConfigureTransport
498+
// Likewise, DisableKeepAlives from h1 is used too.
499+
500+
// Protocols field is only used when the request is not using TLS,
501+
// http1/2 over tls is still allowed
502+
if slices.Contains(h.Versions, "h2c") {
503+
rt.Protocols = new(http.Protocols)
504+
rt.Protocols.SetUnencryptedHTTP2(true)
505+
rt.Protocols.SetHTTP1(false)
515506
}
516-
h.h2cTransport = h2t
517507
}
518508

519509
return rt, nil
@@ -528,15 +518,6 @@ func (h *HTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) {
528518
return h.h3Transport.RoundTrip(req)
529519
}
530520

531-
// if H2C ("HTTP/2 over cleartext") is enabled and the upstream request is
532-
// HTTP without TLS, use the alternate H2C-capable transport instead
533-
if req.URL.Scheme == "http" && h.h2cTransport != nil {
534-
// There is no dedicated DisableKeepAlives field in *http2.Transport.
535-
// This is an alternative way to disable keep-alive.
536-
req.Close = h.Transport.DisableKeepAlives
537-
return h.h2cTransport.RoundTrip(req)
538-
}
539-
540521
return h.Transport.RoundTrip(req)
541522
}
542523

0 commit comments

Comments
 (0)