gzip_handler.go 1.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. package util
  2. import (
  3. "compress/gzip"
  4. "io"
  5. "io/ioutil"
  6. "net/http"
  7. "strings"
  8. "sync"
  9. )
  10. // Gzip is a HTTP middleware to transparently compress responses using gzip.
  11. // Original code from https://gist.github.com/CJEnright/bc2d8b8dc0c1389a9feeddb110f822d7 (MIT)
  12. func Gzip(next http.Handler) http.Handler {
  13. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  14. if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
  15. next.ServeHTTP(w, r)
  16. return
  17. }
  18. w.Header().Set("Content-Encoding", "gzip")
  19. gz := gzPool.Get().(*gzip.Writer)
  20. defer gzPool.Put(gz)
  21. gz.Reset(w)
  22. defer gz.Close()
  23. r.Header.Del("Accept-Encoding") // prevent double-gzipping
  24. next.ServeHTTP(&gzipResponseWriter{ResponseWriter: w, Writer: gz}, r)
  25. })
  26. }
  27. var gzPool = sync.Pool{
  28. New: func() interface{} {
  29. w := gzip.NewWriter(ioutil.Discard)
  30. return w
  31. },
  32. }
  33. type gzipResponseWriter struct {
  34. io.Writer
  35. http.ResponseWriter
  36. }
  37. func (w *gzipResponseWriter) WriteHeader(status int) {
  38. w.Header().Del("Content-Length")
  39. w.ResponseWriter.WriteHeader(status)
  40. }
  41. func (w *gzipResponseWriter) Write(b []byte) (int, error) {
  42. return w.Writer.Write(b)
  43. }