Roll your own gzip-encoded HTTP handler
While I’m sure we’ll have “out of the box” support for gzip-compressed HTTP responses pretty soon, it’s quite easy to do it yourself.
package main
import (
"compress/gzip"
"http"
"io"
"os"
"strings"
)
type gzipResponseWriter struct {
io.Writer
http.ResponseWriter
}
func (w gzipResponseWriter) Write(b []byte) (int, os.Error) {
return w.Writer.Write(b)
}
func makeGzipHandler(fn http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
fn(w, r)
return
}
w.Header().Set("Content-Encoding", "gzip")
gz, err := gzip.NewWriter(w)
if err != nil {
http.Error(w, err.String(), http.StatusInternalServerError)
return
}
defer gz.Close()
fn(gzipResponseWriter{Writer: gz, ResponseWriter: w}, r)
}
}
func handler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("This is a test."))
}
func main() {
http.ListenAndServe(":8081", makeGzipHandler(handler))
}One nicety this demonstrates is how easy it is to substitute a subset
of one interface’s methods with those of another. The
gzipResponseWriter has two embedded values. The methods from
http.ReponseWriter that don’t conflict with the io.Writer are simply
inherited. But because the http.ResponseWriter and io.Writer both
have a Write method, we must write a shim Write method to pass
through to the io.Writer.