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
,请妥善处理上述问题。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于