...
1 package gzip
2
3 import (
4 "compress/gzip"
5 "net/http"
6 "path/filepath"
7 "strings"
8
9 "github.com/gin-gonic/gin"
10 )
11
12 const (
13 BestCompression = gzip.BestCompression
14 BestSpeed = gzip.BestSpeed
15 DefaultCompression = gzip.DefaultCompression
16 NoCompression = gzip.NoCompression
17 )
18
19 func Gzip(level int) gin.HandlerFunc {
20 return func(c *gin.Context) {
21 if !shouldCompress(c.Request) {
22 return
23 }
24 gz, err := gzip.NewWriterLevel(c.Writer, level)
25 if err != nil {
26 return
27 }
28
29 c.Header("Content-Encoding", "gzip")
30 c.Header("Vary", "Accept-Encoding")
31 c.Writer = &gzipWriter{c.Writer, gz}
32 defer func() {
33 c.Header("Content-Length", "0")
34 gz.Close()
35 }()
36 c.Next()
37 }
38 }
39
40 type gzipWriter struct {
41 gin.ResponseWriter
42 writer *gzip.Writer
43 }
44
45 func (g *gzipWriter) WriteString(s string) (int, error) {
46 return g.writer.Write([]byte(s))
47 }
48
49 func (g *gzipWriter) Write(data []byte) (int, error) {
50 return g.writer.Write(data)
51 }
52
53 func shouldCompress(req *http.Request) bool {
54 if !strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") {
55 return false
56 }
57 extension := filepath.Ext(req.URL.Path)
58 if len(extension) < 4 {
59 return true
60 }
61
62 switch extension {
63 case ".png", ".gif", ".jpeg", ".jpg":
64 return false
65 default:
66 return true
67 }
68 }
69
View as plain text