适用于 Gin 和 net/http 的 gzip 中间件,基于 Content-Type、Content-Length、扩展名等要素自动判断是否启用压缩
資深大佬 : nanmu42 64
gzip 中间件
项目地址: https://github.com/nanmu42/gzip
适用于Gin和net/http的 gzip 中间件。基于 Content-Type、Content-Length、扩展名等要素自动判断是否启用压缩。
使用示例
Gin
import github.com/nanmu42/gzip func main() { g := gin.Default() // 使用默认设定 g.Use(gzip.DefaultHandler().Gin) g.GET("/", func(c *gin.Context) { c.JSON( http.StatusOK, map[string]interface{}{ "code": 0, "msg": "hello", "data": fmt.Sprintf("l%sng!", strings.Repeat("o", 1000)), }) }) log.Println(g.Run(fmt.Sprintf(":%d", 3000))) }
net/http
import github.com/nanmu42/gzip func main() { mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { writeString(w, fmt.Sprintf("This content is compressed: l%sng!", strings.Repeat("o", 1000))) }) // 使用默认设定 log.Println( http.ListenAndServe(fmt.Sprintf(":%d", 3001), gzip.DefaultHandler().WrapHandler(mux))) } func writeString(w http.ResponseWriter, payload string) { w.Header().Set("Content-Type", "text/plain; charset=utf8") _, _ = io.WriteString(w, payload+"n") }
定制Handler
在创建Handler时,可以定制参数以满足你的需要:
import github.com/nanmu42/gzip handler := gzip.NewHandler(gzip.Config{ // gzip 压缩等级 CompressionLevel: 6, // 使用 gzip 的最小 body 体积,单位:byte MinContentLength: 256, // 请求过滤器基于请求来判断是否对这条请求的返回启用 gzip, // 过滤器按其定义顺序执行,下同。 RequestFilter: []RequestFilter{ NewCommonRequestFilter(), DefaultExtensionFilter(), }, // 返回 header 过滤器基于返回的 header 判断是否对这条请求的返回启用 gzip ResponseHeaderFilter: []ResponseHeaderFilter{ NewSkipCompressedFilter(), DefaultContentTypeFilter(), }, })
RequestFilter 和 ResponseHeaderFilter 是 interface. 你可以实现你自己的过滤器。
Handler 的局限性
- 总是在返回中提供
Content-Type,Handler 不会对未知Content-Type的返回进行类型猜测; - Handler 会先在返回的
Content-Length中查询 body 体积,如果没有就再查看http.ResponseWriter.Write(data []byte)在首次调用时的len(data)作为参考。倘若返回的Content-Length不存在,且http.ResponseWriter.Write(data []byte)首次调用时的len(data)较小,这条返回会被错误认为无需压缩。
如果你使用的是 Gin 的c.JSON()或c.PureJSON(),无需担心上述问题。
如果你直接使用net/http,请妥善处理上述问题。
大佬有話說 (2)