forked from quic-go/quic-go
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:
@@ -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.
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user