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