Skip to content

Commit

Permalink
Issue valyala#176: reset Content-Length when compression is enabled f…
Browse files Browse the repository at this point in the history
…or streamed response body
  • Loading branch information
valyala committed Jun 27, 2017
1 parent 0f5182f commit 8948e04
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 4 deletions.
18 changes: 14 additions & 4 deletions http.go
Original file line number Diff line number Diff line change
Expand Up @@ -1194,9 +1194,14 @@ func (resp *Response) gzipBody(level int) error {
return nil
}

// Do not care about memory allocations here, since gzip is slow
// and allocates a lot of memory by itself.
if resp.bodyStream != nil {
// Reset Content-Length to -1, since it is impossible
// to determine body size beforehand of streamed compression.
// For https://github.com/valyala/fasthttp/issues/176 .
resp.Header.SetContentLength(-1)

// Do not care about memory allocations here, since gzip is slow
// and allocates a lot of memory by itself.
bs := resp.bodyStream
resp.bodyStream = NewStreamReader(func(sw *bufio.Writer) {
zw := acquireStacklessGzipWriter(sw, level)
Expand Down Expand Up @@ -1243,9 +1248,14 @@ func (resp *Response) deflateBody(level int) error {
return nil
}

// Do not care about memory allocations here, since flate is slow
// and allocates a lot of memory by itself.
if resp.bodyStream != nil {
// Reset Content-Length to -1, since it is impossible
// to determine body size beforehand of streamed compression.
// For https://github.com/valyala/fasthttp/issues/176 .
resp.Header.SetContentLength(-1)

// Do not care about memory allocations here, since flate is slow
// and allocates a lot of memory by itself.
bs := resp.bodyStream
resp.bodyStream = NewStreamReader(func(sw *bufio.Writer) {
zw := acquireStacklessDeflateWriter(sw, level)
Expand Down
72 changes: 72 additions & 0 deletions http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,78 @@ import (
"time"
)

func TestResponseBodyStreamDeflate(t *testing.T) {
body := createFixedBody(1e5)

// Verifies https://github.com/valyala/fasthttp/issues/176
// when Content-Length is explicitly set.
testResponseBodyStreamDeflate(t, body, len(body))

// Verifies that 'transfer-encoding: chunked' works as expected.
testResponseBodyStreamDeflate(t, body, -1)
}

func TestResponseBodyStreamGzip(t *testing.T) {
body := createFixedBody(1e5)

// Verifies https://github.com/valyala/fasthttp/issues/176
// when Content-Length is explicitly set.
testResponseBodyStreamGzip(t, body, len(body))

// Verifies that 'transfer-encoding: chunked' works as expected.
testResponseBodyStreamGzip(t, body, -1)
}

func testResponseBodyStreamDeflate(t *testing.T, body []byte, bodySize int) {
var r Response
r.SetBodyStream(bytes.NewReader(body), bodySize)

w := &bytes.Buffer{}
bw := bufio.NewWriter(w)
if err := r.WriteDeflate(bw); err != nil {
t.Fatalf("unexpected error: %s", err)
}

var resp Response
br := bufio.NewReader(w)
if err := resp.Read(br); err != nil {
t.Fatalf("unexpected error: %s", err)
}

respBody, err := resp.BodyInflate()
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if !bytes.Equal(respBody, body) {
t.Fatalf("unexpected body: %q. Expecting %q", respBody, body)
}
}

func testResponseBodyStreamGzip(t *testing.T, body []byte, bodySize int) {
var r Response
r.SetBodyStream(bytes.NewReader(body), bodySize)

w := &bytes.Buffer{}
bw := bufio.NewWriter(w)
if err := r.WriteGzip(bw); err != nil {
t.Fatalf("unexpected error: %s", err)
}

var resp Response
br := bufio.NewReader(w)
if err := resp.Read(br); err != nil {
t.Fatalf("unexpected error: %s", err)
}

respBody, err := resp.BodyGunzip()
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if !bytes.Equal(respBody, body) {
t.Fatalf("unexpected body: %q. Expecting %q", respBody, body)
}
}

func TestResponseWriteGzipNilBody(t *testing.T) {
var r Response
w := &bytes.Buffer{}
Expand Down

0 comments on commit 8948e04

Please sign in to comment.