--- /dev/null
+package gzip
+
+import (
+ "bufio"
+ "compress/gzip"
+ "errors"
+ "io"
+ "net"
+ "net/http"
+ "strings"
+ "sync"
+)
+
+var pool = sync.Pool{
+ New: func() interface{} {
+ w, _ := gzip.NewWriterLevel(nil, gzip.BestSpeed) // #nosec
+ return w
+ },
+}
+
+func getWriter(w io.Writer) *gzip.Writer {
+ gz := pool.Get().(*gzip.Writer)
+ gz.Reset(w)
+ return gz
+}
+
+type Handler struct {
+ Handler http.Handler
+}
+
+func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ w.Header().Add("Vary", "Accept-Encoding")
+ if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
+ h.Handler.ServeHTTP(w, r)
+ return
+ }
+ w.Header().Set("Content-Encoding", "gzip")
+ gz := getWriter(w)
+ w = &responseWriter{gz, w}
+ h.Handler.ServeHTTP(w, r)
+ gz.Close()
+ pool.Put(gz)
+}
+
+type responseWriter struct {
+ w io.Writer // w wraps only method Write
+ http.ResponseWriter // embedded for the other methods
+}
+
+var _ http.ResponseWriter = (*responseWriter)(nil)
+var _ http.Hijacker = (*responseWriter)(nil)
+
+func (w *responseWriter) Write(p []byte) (int, error) { return w.w.Write(p) }
+
+func (w *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+ h, ok := w.ResponseWriter.(http.Hijacker)
+ if !ok {
+ return nil, nil, errors.New("not a hijacker")
+ }
+ return h.Hijack()
+}