@marcel91200 / caddy Mirror · read-only / commits / 1e21b660
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 11, 19:45 UTC

reverseproxy: use http.Protocols to handle h2c requests (#6990)

WeidiDeng committed Oct 22, 2025 at 00:05 UTC 1e21b660c42485cb47287b595900446093d3df2b
1 file changed +15 -34
modules/caddyhttp/reverseproxy/httptransport.go
+15 -34
@@ -160,8 +160,7 @@ type HTTPTransport struct {
160 // `HTTPS_PROXY`, and `NO_PROXY` environment variables.
161 NetworkProxyRaw json.RawMessage `json:"network_proxy,omitempty" caddy:"namespace=caddy.network_proxy inline_key=from"`
162
163 - h2cTransport *http2.Transport
164 - h3Transport *http3.Transport // TODO: EXPERIMENTAL (May 2024)
163 + h3Transport *http3.Transport // TODO: EXPERIMENTAL (May 2024)
164 }
165
166 // CaddyModule returns the Caddy module information.
@@ -472,12 +471,6 @@ func (h *HTTPTransport) NewTransport(caddyCtx caddy.Context) (*http.Transport, e
471 rt.DisableCompression = !*h.Compression
472 }
473
475 - if slices.Contains(h.Versions, "2") {
476 - if err := http2.ConfigureTransport(rt); err != nil {
477 - return nil, err
478 - }
479 - }
480 -
474 // configure HTTP/3 transport if enabled; however, this does not
475 // automatically fall back to lower versions like most web browsers
476 // 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
488 return nil, fmt.Errorf("if HTTP/3 is enabled to the upstream, no other HTTP versions are supported")
489 }
490
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
495 }
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)
506 }
516 - h.h2cTransport = h2t
507 }
508
509 return rt, nil
@@ -528,15 +518,6 @@ func (h *HTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) {
518 return h.h3Transport.RoundTrip(req)
519 }
520
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 -
521 return h.Transport.RoundTrip(req)
522 }
523