diff --git a/caddytest/integration/webtransport_echo_test.go b/caddytest/integration/webtransport_echo_test.go index 58a66244e..b06af4a97 100644 --- a/caddytest/integration/webtransport_echo_test.go +++ b/caddytest/integration/webtransport_echo_test.go @@ -41,9 +41,14 @@ func init() { caddy.RegisterModule(WebTransportEcho{}) } -// webtransportEchoProtocol is the :protocol pseudo-header value for an -// HTTP/3 Extended CONNECT that establishes a WebTransport session. -const webtransportEchoProtocol = "webtransport" +// webtransportEchoProtocol values are the :protocol pseudo-header tokens for +// an HTTP/3 Extended CONNECT that establishes a WebTransport session. draft-15 +// (webtransport-go v0.11.0+) uses "webtransport-h3"; older draft clients use +// the legacy "webtransport" token. +const ( + webtransportEchoProtocol = "webtransport" + webtransportEchoProtocolDraft15 = "webtransport-h3" +) // webtransportEchoWriter is the naked HTTP/3 response-writer shape that // webtransport.Server.Upgrade type-asserts on. @@ -137,7 +142,7 @@ func (h *WebTransportEcho) echoStreams(session *webtransport.Session) { func isWebTransportEchoUpgrade(r *http.Request) bool { return r.ProtoMajor == 3 && r.Method == http.MethodConnect && - r.Proto == webtransportEchoProtocol + (r.Proto == webtransportEchoProtocol || r.Proto == webtransportEchoProtocolDraft15) } // Interface guards. @@ -157,6 +162,7 @@ func TestIsWebTransportEchoUpgrade(t *testing.T) { want bool }{ {"h3 connect webtransport", "webtransport", 3, http.MethodConnect, true}, + {"h3 connect webtransport-h3", "webtransport-h3", 3, http.MethodConnect, true}, {"h3 connect websocket", "websocket", 3, http.MethodConnect, false}, {"h2 connect webtransport", "webtransport", 2, http.MethodConnect, false}, {"h3 GET", "HTTP/3.0", 3, http.MethodGet, false}, diff --git a/go.mod b/go.mod index 1c6cccb6e..88371fd0f 100644 --- a/go.mod +++ b/go.mod @@ -21,8 +21,8 @@ require ( github.com/klauspost/cpuid/v2 v2.3.0 github.com/mholt/acmez/v3 v3.1.6 github.com/prometheus/client_golang v1.23.2 - github.com/quic-go/quic-go v0.59.1 - github.com/quic-go/webtransport-go v0.10.0 + github.com/quic-go/quic-go v0.60.0 + github.com/quic-go/webtransport-go v0.11.0 github.com/smallstep/certificates v0.30.2 github.com/smallstep/nosql v0.8.0 github.com/smallstep/truststore v0.13.0 diff --git a/go.sum b/go.sum index 181100be7..408d9ee12 100644 --- a/go.sum +++ b/go.sum @@ -287,12 +287,14 @@ github.com/prometheus/otlptranslator v1.0.0 h1:s0LJW/iN9dkIH+EnhiD3BlkkP5QVIUVEo github.com/prometheus/otlptranslator v1.0.0/go.mod h1:vRYWnXvI6aWGpsdY/mOT/cbeVRBlPWtBNDb7kGR3uKM= github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= +github.com/quic-go/go-ossfuzz-seeds v0.1.0 h1:APacT+iIaNF6fd8AGEiN3bT/Jtkd2jz4v4TzM7MFjy0= +github.com/quic-go/go-ossfuzz-seeds v0.1.0/go.mod h1:3IOHRbJIc+L6YKMwfDtJAM9Vj9k0YY4muhuyUYk5tbk= github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= -github.com/quic-go/quic-go v0.59.1 h1:0Gmua0HW1Tv7ANR7hUYwRyD0MG5OJfgvYSZasGZzBic= -github.com/quic-go/quic-go v0.59.1/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= -github.com/quic-go/webtransport-go v0.10.0 h1:LqXXPOXuETY5Xe8ITdGisBzTYmUOy5eSj+9n4hLTjHI= -github.com/quic-go/webtransport-go v0.10.0/go.mod h1:LeGIXr5BQKE3UsynwVBeQrU1TPrbh73MGoC6jd+V7ow= +github.com/quic-go/quic-go v0.60.0 h1:xcQioE8OM66UQLeUMHltK1CCcOu3JbVB4JAQdDQSB+0= +github.com/quic-go/quic-go v0.60.0/go.mod h1:wpKpjmPpftl30sL6pFh7REVpjbcCVy4zt2vDyK1TuJk= +github.com/quic-go/webtransport-go v0.11.0 h1:3afiZq7MHv3gmKCbMwZ8D5M1u0y/1RdONN9KlWp32J0= +github.com/quic-go/webtransport-go v0.11.0/go.mod h1:SHgEzUFVyj+9WUSuGB1P6Zd351Pww2leWV3SwlTovkA= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= diff --git a/modules/caddyhttp/reverseproxy/webtransport_transport.go b/modules/caddyhttp/reverseproxy/webtransport_transport.go index a7670ed97..6a42fb46d 100644 --- a/modules/caddyhttp/reverseproxy/webtransport_transport.go +++ b/modules/caddyhttp/reverseproxy/webtransport_transport.go @@ -30,10 +30,15 @@ import ( "github.com/caddyserver/caddy/v2/modules/caddyhttp" ) -// webtransportProtocol is the :protocol pseudo-header value sent by a -// client that wants to establish a WebTransport session over an HTTP/3 -// Extended CONNECT. -const webtransportProtocol = "webtransport" +// webtransportProtocol values are the :protocol pseudo-header tokens sent +// by a client that wants to establish a WebTransport session over an HTTP/3 +// Extended CONNECT. draft-15 (webtransport-go v0.11.0+) uses "webtransport-h3"; +// older draft clients use the legacy "webtransport" token, which the +// webtransport-go server still accepts. Detect both. +const ( + webtransportProtocol = "webtransport" + webtransportProtocolDraft15 = "webtransport-h3" +) // webtransportWriter is the naked HTTP/3 response-writer shape that // webtransport.Server.Upgrade type-asserts on. Caddy's @@ -49,7 +54,8 @@ type webtransportWriter interface { // CONNECT that requests a WebTransport session. Does not check whether // WebTransport proxying is configured; callers gate on Handler state. func isWebTransportExtendedConnect(r *http.Request) bool { - return r.ProtoMajor == 3 && r.Method == http.MethodConnect && r.Proto == webtransportProtocol + return r.ProtoMajor == 3 && r.Method == http.MethodConnect && + (r.Proto == webtransportProtocol || r.Proto == webtransportProtocolDraft15) } // webTransportTransport is implemented by reverse-proxy transports that