github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/net/http/gzip/gzip.go (about) 1 package gzip 2 3 import ( 4 "bufio" 5 "compress/gzip" 6 "errors" 7 "io" 8 "net" 9 "net/http" 10 "strings" 11 "sync" 12 ) 13 14 var pool = sync.Pool{ 15 New: func() interface{} { 16 w, _ := gzip.NewWriterLevel(nil, gzip.BestSpeed) // #nosec 17 return w 18 }, 19 } 20 21 func getWriter(w io.Writer) *gzip.Writer { 22 gz := pool.Get().(*gzip.Writer) 23 gz.Reset(w) 24 return gz 25 } 26 27 type Handler struct { 28 Handler http.Handler 29 } 30 31 func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 32 w.Header().Add("Vary", "Accept-Encoding") 33 if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { 34 h.Handler.ServeHTTP(w, r) 35 return 36 } 37 w.Header().Set("Content-Encoding", "gzip") 38 gz := getWriter(w) 39 w = &responseWriter{gz, w} 40 h.Handler.ServeHTTP(w, r) 41 gz.Close() 42 pool.Put(gz) 43 } 44 45 type responseWriter struct { 46 w io.Writer // w wraps only method Write 47 http.ResponseWriter // embedded for the other methods 48 } 49 50 var _ http.ResponseWriter = (*responseWriter)(nil) 51 var _ http.Hijacker = (*responseWriter)(nil) 52 53 func (w *responseWriter) Write(p []byte) (int, error) { return w.w.Write(p) } 54 55 func (w *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { 56 h, ok := w.ResponseWriter.(http.Hijacker) 57 if !ok { 58 return nil, nil, errors.New("not a hijacker") 59 } 60 return h.Hijack() 61 }