forked from quic-go/quic-go
http3: set ContentLength to -1 if no Content-Length header is set (#4645)
This applies to both the http.Response and the http.Request.
This commit is contained in:
@@ -22,7 +22,7 @@ type header struct {
|
||||
Status string
|
||||
// for Extended connect
|
||||
Protocol string
|
||||
// parsed and deduplicated
|
||||
// parsed and deduplicated. -1 if no Content-Length header is sent
|
||||
ContentLength int64
|
||||
// all non-pseudo headers
|
||||
Headers http.Header
|
||||
@@ -91,6 +91,7 @@ func parseHeaders(headers []qpack.HeaderField, isRequest bool) (header, error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
hdr.ContentLength = -1
|
||||
if len(contentLengthStr) > 0 {
|
||||
// use ParseUint instead of ParseInt, so that parsing fails on negative values
|
||||
cl, err := strconv.ParseUint(contentLengthStr, 10, 63)
|
||||
|
||||
@@ -33,6 +33,17 @@ var _ = Describe("Request", func() {
|
||||
Expect(req.RequestURI).To(Equal("/foo"))
|
||||
})
|
||||
|
||||
It("sets the ContentLength to -1", func() {
|
||||
headers := []qpack.HeaderField{
|
||||
{Name: ":path", Value: "/foo"},
|
||||
{Name: ":authority", Value: "quic.clemente.io"},
|
||||
{Name: ":method", Value: "GET"},
|
||||
}
|
||||
req, err := requestFromHeaders(headers)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(req.ContentLength).To(BeEquivalentTo(-1))
|
||||
})
|
||||
|
||||
It("rejects upper-case fields", func() {
|
||||
headers := []qpack.HeaderField{
|
||||
{Name: ":path", Value: "/foo"},
|
||||
@@ -343,7 +354,6 @@ var _ = Describe("Response", func() {
|
||||
It("rejects invalid status codes", func() {
|
||||
headers := []qpack.HeaderField{
|
||||
{Name: ":status", Value: "foobar"},
|
||||
{Name: "content-length", Value: "42"},
|
||||
}
|
||||
err := updateResponseFromHeaders(&http.Response{}, headers)
|
||||
Expect(err).To(HaveOccurred())
|
||||
|
||||
@@ -238,11 +238,7 @@ func (s *requestStream) ReadResponse() (*http.Response, error) {
|
||||
|
||||
// Check that the server doesn't send more data in DATA frames than indicated by the Content-Length header (if set).
|
||||
// See section 4.1.2 of RFC 9114.
|
||||
contentLength := int64(-1)
|
||||
if _, ok := res.Header["Content-Length"]; ok && res.ContentLength >= 0 {
|
||||
contentLength = res.ContentLength
|
||||
}
|
||||
respBody := newResponseBody(s.stream, contentLength, s.reqDone)
|
||||
respBody := newResponseBody(s.stream, res.ContentLength, s.reqDone)
|
||||
|
||||
// Rules for when to set Content-Length are defined in https://tools.ietf.org/html/rfc7230#section-3.3.2.
|
||||
isInformational := res.StatusCode >= 100 && res.StatusCode < 200
|
||||
|
||||
@@ -289,6 +289,7 @@ var _ = Describe("HTTP tests", func() {
|
||||
Expect(resp.StatusCode).To(Equal(200))
|
||||
body, err := io.ReadAll(gbytes.TimeoutReader(resp.Body, 20*time.Second))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(resp.ContentLength).To(BeEquivalentTo(-1))
|
||||
Expect(body).To(Equal(PRDataLong))
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user