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
|
Status string
|
||||||
// for Extended connect
|
// for Extended connect
|
||||||
Protocol string
|
Protocol string
|
||||||
// parsed and deduplicated
|
// parsed and deduplicated. -1 if no Content-Length header is sent
|
||||||
ContentLength int64
|
ContentLength int64
|
||||||
// all non-pseudo headers
|
// all non-pseudo headers
|
||||||
Headers http.Header
|
Headers http.Header
|
||||||
@@ -91,6 +91,7 @@ func parseHeaders(headers []qpack.HeaderField, isRequest bool) (header, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hdr.ContentLength = -1
|
||||||
if len(contentLengthStr) > 0 {
|
if len(contentLengthStr) > 0 {
|
||||||
// use ParseUint instead of ParseInt, so that parsing fails on negative values
|
// use ParseUint instead of ParseInt, so that parsing fails on negative values
|
||||||
cl, err := strconv.ParseUint(contentLengthStr, 10, 63)
|
cl, err := strconv.ParseUint(contentLengthStr, 10, 63)
|
||||||
|
|||||||
@@ -33,6 +33,17 @@ var _ = Describe("Request", func() {
|
|||||||
Expect(req.RequestURI).To(Equal("/foo"))
|
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() {
|
It("rejects upper-case fields", func() {
|
||||||
headers := []qpack.HeaderField{
|
headers := []qpack.HeaderField{
|
||||||
{Name: ":path", Value: "/foo"},
|
{Name: ":path", Value: "/foo"},
|
||||||
@@ -343,7 +354,6 @@ var _ = Describe("Response", func() {
|
|||||||
It("rejects invalid status codes", func() {
|
It("rejects invalid status codes", func() {
|
||||||
headers := []qpack.HeaderField{
|
headers := []qpack.HeaderField{
|
||||||
{Name: ":status", Value: "foobar"},
|
{Name: ":status", Value: "foobar"},
|
||||||
{Name: "content-length", Value: "42"},
|
|
||||||
}
|
}
|
||||||
err := updateResponseFromHeaders(&http.Response{}, headers)
|
err := updateResponseFromHeaders(&http.Response{}, headers)
|
||||||
Expect(err).To(HaveOccurred())
|
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).
|
// 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.
|
// See section 4.1.2 of RFC 9114.
|
||||||
contentLength := int64(-1)
|
respBody := newResponseBody(s.stream, res.ContentLength, s.reqDone)
|
||||||
if _, ok := res.Header["Content-Length"]; ok && res.ContentLength >= 0 {
|
|
||||||
contentLength = res.ContentLength
|
|
||||||
}
|
|
||||||
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.
|
// 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
|
isInformational := res.StatusCode >= 100 && res.StatusCode < 200
|
||||||
|
|||||||
@@ -289,6 +289,7 @@ var _ = Describe("HTTP tests", func() {
|
|||||||
Expect(resp.StatusCode).To(Equal(200))
|
Expect(resp.StatusCode).To(Equal(200))
|
||||||
body, err := io.ReadAll(gbytes.TimeoutReader(resp.Body, 20*time.Second))
|
body, err := io.ReadAll(gbytes.TimeoutReader(resp.Body, 20*time.Second))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(resp.ContentLength).To(BeEquivalentTo(-1))
|
||||||
Expect(body).To(Equal(PRDataLong))
|
Expect(body).To(Equal(PRDataLong))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user