From 5dedb7e12ceb388d3e17caf0c1d11182daa33b22 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Mon, 25 Apr 2022 12:20:58 +0100 Subject: [PATCH] fix parsing of request path for Extended CONNECT requests (#3388) --- http3/request.go | 29 ++++++++++++++++++----------- http3/request_test.go | 5 +++-- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/http3/request.go b/http3/request.go index e98ab7fa..f15e8afc 100644 --- a/http3/request.go +++ b/http3/request.go @@ -42,13 +42,14 @@ func requestFromHeaders(headers []qpack.HeaderField) (*http.Request, error) { } isConnect := method == http.MethodConnect - if isConnect { - // Extended CONNECT, see https://datatracker.ietf.org/doc/html/rfc8441#section-4 - if protocol != "" { - if scheme == "" || path == "" || authority == "" { - return nil, errors.New("extended CONNECT: :scheme, :path and :authority must not be empty") - } - } else if path != "" || authority == "" { // normal CONNECT + // Extended CONNECT, see https://datatracker.ietf.org/doc/html/rfc8441#section-4 + isExtendedConnected := isConnect && protocol != "" + if isExtendedConnected { + if scheme == "" || path == "" || authority == "" { + return nil, errors.New("extended CONNECT: :scheme, :path and :authority must not be empty") + } + } else if isConnect { + if path != "" || authority == "" { // normal CONNECT return nil, errors.New(":path must be empty and :authority must not be empty") } } else if len(path) == 0 || len(authority) == 0 || len(method) == 0 { @@ -60,11 +61,17 @@ func requestFromHeaders(headers []qpack.HeaderField) (*http.Request, error) { var err error if isConnect { - u = &url.URL{ - Scheme: scheme, - Host: authority, - Path: path, + u = &url.URL{} + if isExtendedConnected { + u, err = url.ParseRequestURI(path) + if err != nil { + return nil, err + } + } else { + u.Path = path } + u.Scheme = scheme + u.Host = authority requestURI = authority } else { protocol = "HTTP/3" diff --git a/http3/request_test.go b/http3/request_test.go index 006cc0be..ec3aa8b3 100644 --- a/http3/request_test.go +++ b/http3/request_test.go @@ -146,13 +146,14 @@ var _ = Describe("Request", func() { {Name: ":scheme", Value: "ftp"}, {Name: ":method", Value: http.MethodConnect}, {Name: ":authority", Value: "quic.clemente.io"}, - {Name: ":path", Value: "/foo"}, + {Name: ":path", Value: "/foo?val=1337"}, } req, err := requestFromHeaders(headers) Expect(err).NotTo(HaveOccurred()) Expect(req.Method).To(Equal(http.MethodConnect)) Expect(req.Proto).To(Equal("webtransport")) - Expect(req.URL.String()).To(Equal("ftp://quic.clemente.io/foo")) + Expect(req.URL.String()).To(Equal("ftp://quic.clemente.io/foo?val=1337")) + Expect(req.URL.Query().Get("val")).To(Equal("1337")) }) It("errors with missing scheme", func() {