| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778 |
- package gzip
- import (
- "compress/gzip"
- "io/ioutil"
- "net/http"
- "path/filepath"
- "strings"
- "sync"
- "github.com/gin-gonic/gin"
- )
- const (
- BestCompression = gzip.BestCompression
- BestSpeed = gzip.BestSpeed
- DefaultCompression = gzip.DefaultCompression
- NoCompression = gzip.NoCompression
- )
- func Gzip(level int) gin.HandlerFunc {
- var gzPool sync.Pool
- gzPool.New = func() interface{} {
- gz, err := gzip.NewWriterLevel(ioutil.Discard, level)
- if err != nil {
- panic(err)
- }
- return gz
- }
- return func(c *gin.Context) {
- if !shouldCompress(c.Request) {
- return
- }
- gz := gzPool.Get().(*gzip.Writer)
- defer gzPool.Put(gz)
- gz.Reset(c.Writer)
- c.Header("Content-Encoding", "gzip")
- c.Header("Vary", "Accept-Encoding")
- c.Writer = &gzipWriter{c.Writer, gz}
- defer func() {
- c.Header("Content-Length", "0")
- gz.Close()
- }()
- c.Next()
- }
- }
- type gzipWriter struct {
- gin.ResponseWriter
- writer *gzip.Writer
- }
- func (g *gzipWriter) WriteString(s string) (int, error) {
- return g.writer.Write([]byte(s))
- }
- func (g *gzipWriter) Write(data []byte) (int, error) {
- return g.writer.Write(data)
- }
- func shouldCompress(req *http.Request) bool {
- if !strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") {
- return false
- }
- extension := filepath.Ext(req.URL.Path)
- if len(extension) < 4 { // fast path
- return true
- }
- switch extension {
- case ".png", ".gif", ".jpeg", ".jpg":
- return false
- default:
- return true
- }
- }
|