Repository: labstack/echo
Pull request #1317 (2019-04-09 12:44:53)

Fix flushing in Gzip middleware
This Pull Request makes the `Flush()` method of response writer in the Gzip middleware call `Flush` on the underlying response writer, instead of only on the gzip writer.

I also added an extra test case that asserts that the headers and first bytes are written and flushed after `Flush()` is called for the first time.

codecov[bot]: # [Codecov](https://codecov.io/gh/labstack/echo/pull/1317?src=pr&el=h1) Report
> Merging [#1317](https://codecov.io/gh/labstack/echo/pull/1317?src=pr&el=desc) into [master](https://codecov.io/gh/labstack/echo/commit/e3717be4beda1dcc2e5163c8b3fbdf0f2e365ace?src=pr&el=desc) will **increase** coverage by `0.11%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/labstack/echo/pull/1317/graphs/tree.svg?width=650&token=vqnT76l79i&height=150&src=pr)](https://codecov.io/gh/labstack/echo/pull/1317?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #1317      +/-   ##
==========================================
+ Coverage   84.27%   84.38%   +0.11%     
==========================================
  Files          27       27              
  Lines        1990     1992       +2     
==========================================
+ Hits         1677     1681       +4     
+ Misses        205      203       -2     
  Partials      108      108
```


| [Impacted Files](https://codecov.io/gh/labstack/echo/pull/1317?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [middleware/compress.go](https://codecov.io/gh/labstack/echo/pull/1317/diff?src=pr&el=tree#diff-bWlkZGxld2FyZS9jb21wcmVzcy5nbw==) | `77.27% <100%> (+5.84%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/labstack/echo/pull/1317?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/labstack/echo/pull/1317?src=pr&el=footer). Last update [e3717be...b95ffbc](https://codecov.io/gh/labstack/echo/pull/1317?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/middleware/compress.go b/middleware/compress.go
index 1905206..89da16e 100644
--- a/middleware/compress.go
+++ b/middleware/compress.go
@@ -111,6 +111,9 @@ func (w *gzipResponseWriter) Write(b []byte) (int, error) {
 
 func (w *gzipResponseWriter) Flush() {
 	w.Writer.(*gzip.Writer).Flush()
+	if flusher, ok := w.ResponseWriter.(http.Flusher); ok {
+		flusher.Flush()
+	}
 }
 
 func (w *gzipResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {


Test patch:
diff --git a/middleware/compress_test.go b/middleware/compress_test.go
index dc7d78c..ac5b6c3 100644
--- a/middleware/compress_test.go
+++ b/middleware/compress_test.go
@@ -3,6 +3,7 @@ package middleware
 import (
 	"bytes"
 	"compress/gzip"
+	"io"
 	"io/ioutil"
 	"net/http"
 	"net/http/httptest"
@@ -44,6 +45,49 @@ func TestGzip(t *testing.T) {
 		buf.ReadFrom(r)
 		assert.Equal("test", buf.String())
 	}
+
+	chunkBuf := make([]byte, 5)
+
+	// Gzip chunked
+	req = httptest.NewRequest(http.MethodGet, "/", nil)
+	req.Header.Set(echo.HeaderAcceptEncoding, gzipScheme)
+	rec = httptest.NewRecorder()
+
+	c = e.NewContext(req, rec)
+	Gzip()(func(c echo.Context) error {
+		c.Response().Header().Set("Content-Type", "text/event-stream")
+		c.Response().Header().Set("Transfer-Encoding", "chunked")
+
+		// Write and flush the first part of the data
+		c.Response().Write([]byte("test\n"))
+		c.Response().Flush()
+
+		// Read the first part of the data
+		assert.True(rec.Flushed)
+		assert.Equal(gzipScheme, rec.Header().Get(echo.HeaderContentEncoding))
+		r.Reset(rec.Body)
+
+		_, err = io.ReadFull(r, chunkBuf)
+		assert.NoError(err)
+		assert.Equal("test\n", string(chunkBuf))
+
+		// Write and flush the second part of the data
+		c.Response().Write([]byte("test\n"))
+		c.Response().Flush()
+
+		_, err = io.ReadFull(r, chunkBuf)
+		assert.NoError(err)
+		assert.Equal("test\n", string(chunkBuf))
+
+		// Write the final part of the data and return
+		c.Response().Write([]byte("test"))
+		return nil
+	})(c)
+
+	buf := new(bytes.Buffer)
+	defer r.Close()
+	buf.ReadFrom(r)
+	assert.Equal("test", buf.String())
 }
 
 func TestGzipNoContent(t *testing.T) {