http3: reject the Transfer-Encoding header field (#4646)

The use of Transfer-Encoding is forbidden in HTTP/3, see section 4.1 of
RFC 9114.
This commit is contained in:
Marten Seemann
2024-08-28 20:31:58 +08:00
committed by GitHub
parent 920bfb46af
commit 229937c503
4 changed files with 14 additions and 6 deletions

View File

@@ -75,6 +75,8 @@ func parseHeaders(headers []qpack.HeaderField, isRequest bool) (header, error) {
}
readFirstRegularHeader = true
switch h.Name {
case "transfer-encoding":
return header{}, errors.New("invalid header field: Transfer-Encoding")
case "content-length":
// Ignore duplicate Content-Length headers.
// Fail if the duplicates differ.

View File

@@ -359,6 +359,15 @@ var _ = Describe("Response", func() {
Expect(err).To(MatchError("invalid response pseudo header: :method"))
})
It("rejects the Transfer-Encoding header field", func() {
headers := []qpack.HeaderField{
{Name: ":status", Value: "404"},
{Name: "transfer-encoding", Value: "chunked"},
}
err := updateResponseFromHeaders(&http.Response{}, headers)
Expect(err).To(MatchError("invalid header field: Transfer-Encoding"))
})
It("parses trailers", func() {
headers := []qpack.HeaderField{
{Name: "content-length", Value: "42"},

View File

@@ -245,11 +245,10 @@ func (s *requestStream) ReadResponse() (*http.Response, error) {
respBody := newResponseBody(s.stream, contentLength, s.reqDone)
// Rules for when to set Content-Length are defined in https://tools.ietf.org/html/rfc7230#section-3.3.2.
_, hasTransferEncoding := res.Header["Transfer-Encoding"]
isInformational := res.StatusCode >= 100 && res.StatusCode < 200
isNoContent := res.StatusCode == http.StatusNoContent
isSuccessfulConnect := s.isConnect && res.StatusCode >= 200 && res.StatusCode < 300
if !hasTransferEncoding && !isInformational && !isNoContent && !isSuccessfulConnect {
if !isInformational && !isNoContent && !isSuccessfulConnect {
res.ContentLength = -1
if clens, ok := res.Header["Content-Length"]; ok && len(clens) == 1 {
if clen64, err := strconv.ParseInt(clens[0], 10, 64); err == nil {

View File

@@ -117,11 +117,9 @@ func (w *responseWriter) sniffContentType(p []byte) {
// We can't use `w.header.Get` here since if the Content-Type was set to nil, we shouldn't do sniffing.
_, haveType := w.header["Content-Type"]
// If the Transfer-Encoding or Content-Encoding was set and is non-blank,
// we shouldn't sniff the body.
hasTE := w.header.Get("Transfer-Encoding") != ""
// If the Content-Encoding was set and is non-blank, we shouldn't sniff the body.
hasCE := w.header.Get("Content-Encoding") != ""
if !hasCE && !haveType && !hasTE && len(p) > 0 {
if !hasCE && !haveType && len(p) > 0 {
w.header.Set("Content-Type", http.DetectContentType(p))
}
}