English | 中文
Content-Type
and Content-Length
aware gzip middleware for Gin and net/http.
import github.com/nanmu42/gzip
func main() {
g := gin.Default()
// use default settings
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)))
}
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)))
})
// wrap http.Handler using default settings
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 can be customized during initialization:
import github.com/nanmu42/gzip
handler := gzip.NewHandler(gzip.Config{
// gzip compression level to use
CompressionLevel: 6,
// minimum content length to trigger gzip, the unit is in byte.
MinContentLength: 256,
// RequestFilter decide whether or not to compress response judging by request.
// Filters are applied in the sequence here.
RequestFilter: []RequestFilter{
NewCommonRequestFilter(),
DefaultExtensionFilter(),
},
// ResponseHeaderFilter decide whether or not to compress response
// judging by request
ResponseHeaderFilter: []ResponseHeaderFilter{
NewSkipCompressedFilter(),
DefaultContentTypeFilter(),
},
})
RequestFilter
and ResponseHeaderFilter
are interfaces.
You may define one that specially suits your need.
- You should always provide a
Content-Type
in http response's header, as handler does not guess; - handler looks up
Content-Length
in http response's header firstly, falls back tolen(data)
of the firsthttp.ResponseWriter.Write(data []byte)
calling. It may not use gzip ifContent-Length
is absent andlen(data)
is low.
If you are using Gin's c.JSON()
or c.PureJSON()
, you are safe from above limitation, as Gin sets proper Content-Type
and write response in full length.
If you are using net/http
, make sure above cases are considered.
API not stabilized, things may breaks.
You are welcome to try gzip on your test/unimportant environments.
Pull requests and issues are welcome.
During the development of this work, the author took following works/materials as reference:
- https://github.com/caddyserver/caddy/tree/master/caddyhttp/gzip (Apache License 2.0)
- https://github.com/gin-contrib/gzip (MIT License)
- https://blog.cloudflare.com/results-experimenting-brotli/
- https://support.cloudflare.com/hc/en-us/articles/200168396-What-will-Cloudflare-compress-
MIT License
Copyright (c) 2019 LI Zhennan
Caddy is licensed under the Apache License
Copyright 2015 Light Code Labs, LLC