diff --git a/handler.go b/handler.go index a595bd2..64a391d 100644 --- a/handler.go +++ b/handler.go @@ -19,12 +19,18 @@ const ( BestCompression = gzip.BestCompression DefaultCompression = gzip.DefaultCompression HuffmanOnly = gzip.HuffmanOnly + // Stateless will do compression but without maintaining any state + // between Write calls, so long running responses will not take memory. + // There will be no memory kept between Write calls, + // but compression and speed will be suboptimal. + // Because of this, the size of actual Write calls will affect output size. + Stateless = gzip.StatelessCompression ) // Config is used in Handler initialization type Config struct { // gzip compression level to use, - // valid value: -2 ~ 9. + // valid value: -3 => 9. // // see https://golang.org/pkg/compress/gzip/#NewWriterLevel CompressionLevel int @@ -58,7 +64,7 @@ type Handler struct { // // config must not be modified after calling on NewHandler() func NewHandler(config Config) *Handler { - if config.CompressionLevel < HuffmanOnly || config.CompressionLevel > BestCompression { + if config.CompressionLevel < Stateless || config.CompressionLevel > BestCompression { panic(fmt.Sprintf("gzip: invalid CompressionLevel: %d", config.CompressionLevel)) } if config.MinContentLength <= 0 { diff --git a/handler_test.go b/handler_test.go index 436b9ec..e23ba93 100644 --- a/handler_test.go +++ b/handler_test.go @@ -113,7 +113,7 @@ func TestNewHandler_Checks(t *testing.T) { assert.Panics(t, func() { NewHandler(Config{ - CompressionLevel: -3, + CompressionLevel: -4, MinContentLength: 100, }) }) @@ -285,6 +285,39 @@ func TestGinWithDefaultHandler(t *testing.T) { } } +func TestGinWithLevelsHandler(t *testing.T) { + for i := Stateless; i < 10; i++ { + var seq = "level_" + strconv.Itoa(i) + i := i + t.Run(seq, func(t *testing.T) { + g := newEchoGinInstance(bigPayload, NewHandler(Config{ + CompressionLevel: i, + MinContentLength: 1, + }).Gin) + + var ( + w = httptest.NewRecorder() + r = httptest.NewRequest(http.MethodPost, "/", strings.NewReader(seq)) + ) + + r.Header.Set("Accept-Encoding", "gzip") + g.ServeHTTP(w, r) + + result := w.Result() + require.EqualValues(t, http.StatusOK, result.StatusCode) + require.Equal(t, "gzip", result.Header.Get("Content-Encoding")) + comp, err := ioutil.ReadAll(result.Body) + require.NoError(t, err) + reader, err := gzip.NewReader(bytes.NewReader(comp)) + require.NoError(t, err) + body, err := ioutil.ReadAll(reader) + require.NoError(t, err) + require.True(t, bytes.HasPrefix(body, []byte(seq))) + t.Logf("%s: compressed %d => %d", seq, len(body), len(comp)) + }) + } +} + func TestGinWithDefaultHandler_404(t *testing.T) { var ( g = newGinInstance(bigPayload, DefaultHandler().Gin)