Reputation: 487
How can I enable gzip compression using the gzip middleware of the go-chi framework?
Try using the example shown here:
https://github.com/go-chi/chi/issues/204
but when I check with curl, I get this:
$ curl -H "Accept-Encoding: gzip" -I http://127.0.0.1:3333
HTTP/1.1 405 Method Not Allowed
Date: Sat, 31 Aug 2019 19:06:39 GMT
I tried the code "hello world":
package main
import (
"net/http"
"github.com/go-chi/chi"
"github.com/go-chi/chi/middleware"
)
func main() {
r := chi.NewRouter()
r.Use(middleware.RequestID)
r.Use(middleware.Logger)
//r.Use(middleware.DefaultCompress) //using this produces the same result
r.Use(middleware.Compress(5, "gzip"))
r.Get("/", Hello)
http.ListenAndServe(":3333", r)
}
func Hello(w http.ResponseWriter, r *http.Request){
w.Header().Set("Content-Type", "text/html") //according to the documentation this must be here to enable gzip
w.Write([]byte("hello world\n"))
}
but when I try to verify with curl, the result is the same
$ curl -H "Accept-Encoding: gzip" -I http://127.0.0.1:3333
HTTP/1.1 405 Method Not Allowed
Date: Sat, 31 Aug 2019 19:06:39 GMT
what's going on?
Upvotes: 0
Views: 6479
Reputation: 981
The problem is the second parameter is the type of content in response body that you want to be compressed, leaving it empty falls back to the defaultCompressibleContentTypes
.
Also, the implementation of this Compress
middleware only accepts deflate
and gzip
in Accept-Encoding
, usually there are br
and zstd
, those 2 are not supported but can be easily extended like this:
func newCompressMiddleware(level int) func(next http.Handler) http.Handler {
compressor := middleware.NewCompressor(level)
// brotli encoder
compressor.SetEncoder("br", func(w io.Writer, level int) io.Writer {
brWriter, err := brotli.NewWriterLevel(w, level)
if err != nil {
return nil
}
return brWriter
})
// zstd encoder
compressor.SetEncoder("zstd", func(w io.Writer, level int) io.Writer {
zstdWriter, err := zstd.NewWriter(w, zstd.WithEncoderLevel(zstd.SpeedDefault))
if err != nil {
return nil
}
return zstdWriter
})
return compressor.Handler
}
Upvotes: 0
Reputation: 2211
The other answers are outdated now. I had to solve this myself, so here what I found out.
Your error is here:
r.Use(middleware.Compress(5, "gzip"))
The second argument ("types") refers to the content types that the compression will be applied to. For example: "text/html"
, "application/json"
, etc
Just add a list of the content-types you want to compress, or remove the argument altogether:
func main() {
r := chi.NewRouter()
r.Use(middleware.RequestID)
r.Use(middleware.Logger)
r.Use(middleware.Compress(5))
r.Get("/", Hello)
http.ListenAndServe(":3333", r)
}
This will compress all the content-types defined in the default list from middleware.Compress:
var defaultCompressibleContentTypes = []string{
"text/html",
"text/css",
"text/plain",
"text/javascript",
"application/javascript",
"application/x-javascript",
"application/json",
"application/atom+xml",
"application/rss+xml",
"image/svg+xml",
}
Good luck!
Upvotes: 14
Reputation: 428
r.Use(middleware.DefaultCompress)
has now been marked as DEPRECATED
.
To enable compression you need to create a compressor, and use its handler.
r := chi.NewRouter()
r.Use(middleware.RequestID)
r.Use(middleware.Logger)
compressor := middleware.NewCompressor(flate.DefaultCompression)
r.Use(compressor.Handler())
r.Get("/", Hello)
http.ListenAndServe(":3333", r)
The flate
package must be imported as compress/flate
.
Upvotes: 8
Reputation: 2755
Use the commented middleware.DefaultCompress
and a normal GET
request.
package main
import (
"net/http"
"github.com/go-chi/chi"
"github.com/go-chi/chi/middleware"
)
func main() {
r := chi.NewRouter()
r.Use(middleware.RequestID)
r.Use(middleware.Logger)
r.Use(middleware.DefaultCompress)
r.Get("/", Hello)
http.ListenAndServe(":3333", r)
}
func Hello(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
w.Write([]byte("hello world\n"))
}
Try with curl
:
$ curl -v http://localhost:3333 --compressed
* Rebuilt URL to: http://localhost:3333/
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 3333 (#0)
> GET / HTTP/1.1
> Host: localhost:3333
> User-Agent: curl/7.58.0
> Accept: */*
> Accept-Encoding: deflate, gzip
>
< HTTP/1.1 200 OK
< Content-Encoding: gzip
< Content-Type: text/html
< Date: Sat, 31 Aug 2019 23:37:52 GMT
< Content-Length: 36
<
hello world
* Connection #0 to host localhost left intact
Or HTTPie
:
$ http :3333
HTTP/1.1 200 OK
Content-Encoding: gzip
Content-Length: 36
Content-Type: text/html
Date: Sat, 31 Aug 2019 23:38:31 GMT
hello world
Upvotes: 0