-
Notifications
You must be signed in to change notification settings - Fork 70
Description
A follow up in a way to #22 I dug in more and found our compression issue only occurs when the response is read from the cache, not the first time when the response is directly pulled from further up the chain. What looks to be happening is that the with the removal of the recorder the new response writer is not tracking the headers that are only from further up the chain.
Our scenario is using a gzip lib to apply compression to responses by providing another wrapped response writer. During this gzip Write call it adds the compression headers. Then after this write is done the cache captures the headers and stores them. When returning a cache result it attaches the Content-Encoding header which causes the gzip lib to consider the body already gziped, which it is not.
Here is a minimum(ish) repro using the same gzip lib.
package main
import (
"fmt"
"math/rand"
"net/http"
"time"
"github.com/klauspost/compress/gzhttp"
cache "github.com/victorspringer/http-cache"
"github.com/victorspringer/http-cache/adapter/memory"
)
const mb = 1024 * 1024
func cacheWrap(next http.Handler) http.Handler {
mcc, _ := memory.NewAdapter(
memory.AdapterWithAlgorithm(memory.LRU),
memory.AdapterWithStorageCapacity(4*mb),
)
cc, _ := cache.NewClient(
cache.ClientWithAdapter(mcc),
cache.ClientWithTTL(time.Minute),
cache.ClientWithMethods([]string{http.MethodGet}),
)
return cc.Middleware(next)
}
func main() {
var content = randString(1024)
fmt.Println(string(content))
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain")
w.Write(content)
})
http.Handle("/", gzhttp.GzipHandler(cacheWrap(handler)))
http.ListenAndServe("0.0.0.0:8000", nil)
}
func randString(length int) []byte {
b := make([]byte, length)
for i := range b {
b[i] = byte(64 + rand.Intn(60))
}
return b
}The behavior I would expect here is to only consider the headers set by the next handler. I've tried swapping the order of the middleware and that just results in no response, but I haven't looked into why, I currently suspect the bug fixed in #24, but haven't confirmed.