Skip to content

Commit 69bd47b

Browse files
htdvisservishr
authored andcommitted
Fix flushing in Gzip middleware (#1317)
* Make Gzip response Writer also call Flush of underlying Writer * Add unit test for chunked responses with Gzip
1 parent e3717be commit 69bd47b

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

middleware/compress.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ func (w *gzipResponseWriter) Write(b []byte) (int, error) {
111111

112112
func (w *gzipResponseWriter) Flush() {
113113
w.Writer.(*gzip.Writer).Flush()
114+
if flusher, ok := w.ResponseWriter.(http.Flusher); ok {
115+
flusher.Flush()
116+
}
114117
}
115118

116119
func (w *gzipResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {

middleware/compress_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package middleware
33
import (
44
"bytes"
55
"compress/gzip"
6+
"io"
67
"io/ioutil"
78
"net/http"
89
"net/http/httptest"
@@ -44,6 +45,49 @@ func TestGzip(t *testing.T) {
4445
buf.ReadFrom(r)
4546
assert.Equal("test", buf.String())
4647
}
48+
49+
chunkBuf := make([]byte, 5)
50+
51+
// Gzip chunked
52+
req = httptest.NewRequest(http.MethodGet, "/", nil)
53+
req.Header.Set(echo.HeaderAcceptEncoding, gzipScheme)
54+
rec = httptest.NewRecorder()
55+
56+
c = e.NewContext(req, rec)
57+
Gzip()(func(c echo.Context) error {
58+
c.Response().Header().Set("Content-Type", "text/event-stream")
59+
c.Response().Header().Set("Transfer-Encoding", "chunked")
60+
61+
// Write and flush the first part of the data
62+
c.Response().Write([]byte("test\n"))
63+
c.Response().Flush()
64+
65+
// Read the first part of the data
66+
assert.True(rec.Flushed)
67+
assert.Equal(gzipScheme, rec.Header().Get(echo.HeaderContentEncoding))
68+
r.Reset(rec.Body)
69+
70+
_, err = io.ReadFull(r, chunkBuf)
71+
assert.NoError(err)
72+
assert.Equal("test\n", string(chunkBuf))
73+
74+
// Write and flush the second part of the data
75+
c.Response().Write([]byte("test\n"))
76+
c.Response().Flush()
77+
78+
_, err = io.ReadFull(r, chunkBuf)
79+
assert.NoError(err)
80+
assert.Equal("test\n", string(chunkBuf))
81+
82+
// Write the final part of the data and return
83+
c.Response().Write([]byte("test"))
84+
return nil
85+
})(c)
86+
87+
buf := new(bytes.Buffer)
88+
defer r.Close()
89+
buf.ReadFrom(r)
90+
assert.Equal("test", buf.String())
4791
}
4892

4993
func TestGzipNoContent(t *testing.T) {

0 commit comments

Comments
 (0)