From 808f849ca220058dbb9c90abe7b6d1a638220d39 Mon Sep 17 00:00:00 2001 From: taoso Date: Fri, 26 Jan 2024 11:07:35 +0800 Subject: [PATCH] http3: only use :protocol pseudo-header for Extended CONNECT (#4261) * Fix protocol The default value should be "HTTP/3.0". * Reject normal request with :protocol header The :protocol pseudo header is only defined for Extended Connect requests (RFC 9220). * save one branch check * Fix review issue --- http3/headers.go | 10 +++++++--- http3/headers_test.go | 12 ++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/http3/headers.go b/http3/headers.go index 79c070b55..040667178 100644 --- a/http3/headers.go +++ b/http3/headers.go @@ -126,9 +126,14 @@ func requestFromHeaders(headerFields []qpack.HeaderField) (*http.Request, error) return nil, errors.New(":path, :authority and :method must not be empty") } + if !isExtendedConnected && len(hdr.Protocol) > 0 { + return nil, errors.New(":protocol must be empty") + } + var u *url.URL var requestURI string - var protocol string + + protocol := "HTTP/3.0" if isConnect { u = &url.URL{} @@ -137,15 +142,14 @@ func requestFromHeaders(headerFields []qpack.HeaderField) (*http.Request, error) if err != nil { return nil, err } + protocol = hdr.Protocol } else { u.Path = hdr.Path } u.Scheme = hdr.Scheme u.Host = hdr.Authority requestURI = hdr.Authority - protocol = hdr.Protocol } else { - protocol = "HTTP/3.0" u, err = url.ParseRequestURI(hdr.Path) if err != nil { return nil, fmt.Errorf("invalid content length: %w", err) diff --git a/http3/headers_test.go b/http3/headers_test.go index 70fac9974..1fb6ccc58 100644 --- a/http3/headers_test.go +++ b/http3/headers_test.go @@ -212,6 +212,17 @@ var _ = Describe("Request", func() { Expect(err).To(MatchError(":path, :authority and :method must not be empty")) }) + It("errors with invalid protocol", func() { + headers := []qpack.HeaderField{ + {Name: ":path", Value: "/foo"}, + {Name: ":authority", Value: "quic.clemente.io"}, + {Name: ":method", Value: "GET"}, + {Name: ":protocol", Value: "connect-udp"}, + } + _, err := requestFromHeaders(headers) + Expect(err).To(MatchError(":protocol must be empty")) + }) + Context("regular HTTP CONNECT", func() { It("handles CONNECT method", func() { headers := []qpack.HeaderField{ @@ -221,6 +232,7 @@ var _ = Describe("Request", func() { req, err := requestFromHeaders(headers) Expect(err).NotTo(HaveOccurred()) Expect(req.Method).To(Equal(http.MethodConnect)) + Expect(req.Proto).To(Equal("HTTP/3.0")) Expect(req.RequestURI).To(Equal("quic.clemente.io")) })