12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273 |
- package gzip
- import (
- "compress/gzip"
- "fmt"
- "io/ioutil"
- "net/http"
- "path/filepath"
- "strings"
- "sync"
- "github.com/gin-gonic/gin"
- )
- type gzipHandler struct {
- *Options
- gzPool sync.Pool
- }
- func newGzipHandler(level int, options ...Option) *gzipHandler {
- var gzPool sync.Pool
- gzPool.New = func() interface{} {
- gz, err := gzip.NewWriterLevel(ioutil.Discard, level)
- if err != nil {
- panic(err)
- }
- return gz
- }
- handler := &gzipHandler{
- Options: DefaultOptions,
- gzPool: gzPool,
- }
- for _, setter := range options {
- setter(handler.Options)
- }
- return handler
- }
- func (g *gzipHandler) Handle(c *gin.Context) {
- if !g.shouldCompress(c.Request) {
- return
- }
- gz := g.gzPool.Get().(*gzip.Writer)
- defer g.gzPool.Put(gz)
- defer gz.Reset(ioutil.Discard)
- gz.Reset(c.Writer)
- c.Header("Content-Encoding", "gzip")
- c.Header("Vary", "Accept-Encoding")
- c.Writer = &gzipWriter{c.Writer, gz}
- defer func() {
- gz.Close()
- c.Header("Content-Length", fmt.Sprint(c.Writer.Size()))
- }()
- c.Next()
- }
- func (g *gzipHandler) shouldCompress(req *http.Request) bool {
- if !strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") ||
- strings.Contains(req.Header.Get("Connection"), "Upgrade") ||
- strings.Contains(req.Header.Get("Content-Type"), "text/event-stream") {
- return false
- }
- extension := filepath.Ext(req.URL.Path)
- if g.ExcludedExtensions.Contains(extension) {
- return false
- }
- return !g.ExcludedPaths.Contains(req.URL.Path)
- }
|