69 lines
1.2 KiB
Go
69 lines
1.2 KiB
Go
|
package gzip
|
||
|
|
||
|
import (
|
||
|
"compress/gzip"
|
||
|
"net/http"
|
||
|
"path/filepath"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/gin-gonic/gin"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
BestCompression = gzip.BestCompression
|
||
|
BestSpeed = gzip.BestSpeed
|
||
|
DefaultCompression = gzip.DefaultCompression
|
||
|
NoCompression = gzip.NoCompression
|
||
|
)
|
||
|
|
||
|
func Gzip(level int) gin.HandlerFunc {
|
||
|
return func(c *gin.Context) {
|
||
|
if !shouldCompress(c.Request) {
|
||
|
return
|
||
|
}
|
||
|
gz, err := gzip.NewWriterLevel(c.Writer, level)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
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
|
||
|
}
|
||
|
}
|