package util import ( "compress/gzip" "io" "io/ioutil" "net/http" "strings" "sync" ) // Gzip is a HTTP middleware to transparently compress responses using gzip. // Original code from https://gist.github.com/CJEnright/bc2d8b8dc0c1389a9feeddb110f822d7 (MIT) func Gzip(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { next.ServeHTTP(w, r) return } w.Header().Set("Content-Encoding", "gzip") gz := gzPool.Get().(*gzip.Writer) defer gzPool.Put(gz) gz.Reset(w) defer gz.Close() r.Header.Del("Accept-Encoding") // prevent double-gzipping next.ServeHTTP(&gzipResponseWriter{ResponseWriter: w, Writer: gz}, r) }) } var gzPool = sync.Pool{ New: func() interface{} { w := gzip.NewWriter(ioutil.Discard) return w }, } type gzipResponseWriter struct { io.Writer http.ResponseWriter } func (w *gzipResponseWriter) WriteHeader(status int) { w.Header().Del("Content-Length") w.ResponseWriter.WriteHeader(status) } func (w *gzipResponseWriter) Write(b []byte) (int, error) { return w.Writer.Write(b) }