Skip to content

Commit

Permalink
Merge pull request #47 from danielgtaylor/fix-double-encoding
Browse files Browse the repository at this point in the history
fix: prevent double content-encoding
  • Loading branch information
danielgtaylor authored May 5, 2022
2 parents e48d986 + 848f168 commit 73c101e
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 0 deletions.
5 changes: 5 additions & 0 deletions middleware/encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ func (w *contentEncodingWriter) Write(data []byte) (int, error) {
return w.writer.Write(data)
}

if w.Header().Get("Content-Encoding") != "" {
// Content encoding was already set, so we should ignore this!
return w.ResponseWriter.Write(data)
}

// Buffer the data until we can decide whether to compress it or not.
w.buf.Write(data)

Expand Down
33 changes: 33 additions & 0 deletions middleware/encoding_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package middleware

import (
"bytes"
"compress/gzip"
"crypto/rand"
"io/ioutil"
"net/http"
"net/http/httptest"
Expand Down Expand Up @@ -200,3 +202,34 @@ func TestContentEncodingPanicBuffered(t *testing.T) {
// when the content encoding writer is closed.
assert.Equal(t, http.StatusInternalServerError, w.Result().StatusCode)
}

func TestContentEncodingIgnore(t *testing.T) {
app, _ := newTestRouter(t)
app.Resource("/").Get("test", "test",
responses.OK(),
).Run(func(ctx huma.Context) {
ctx.Header().Set("Content-Encoding", "br")
buf := make([]byte, 2500)
// Randomize so it can't compress well, which keeps the response
// large enough to potentially double-compress.
rand.Read(buf)
buf[0] = 'H'
buf[1] = 'e'
buf[2] = 'l'
buf[3] = 'l'
buf[4] = 'o'
w := brotli.NewWriter(ctx)
w.Write(buf)
w.Close()
})

w := httptest.NewRecorder()
req, _ := http.NewRequest(http.MethodGet, "/", nil)
req.Header.Add("Accept-Encoding", "br")
app.ServeHTTP(w, req)
assert.Equal(t, http.StatusOK, w.Result().StatusCode)
out := make([]byte, 2500)
_, err := brotli.NewReader(bytes.NewReader(w.Body.Bytes())).Read(out)
assert.NoError(t, err)
assert.Equal(t, []byte{'H', 'e', 'l', 'l', 'o'}, out[:5])
}

0 comments on commit 73c101e

Please sign in to comment.