Gzip Response Compression Middleware

Compress HTTP responses when the client advertises gzip support, set Vary correctly, and skip negotiation for other clients.

GoData Fetching

Code

snippet
package main

import (
	"compress/gzip"
	"fmt"
	"net/http"
	"strings"
)

type gzipWriter struct {
	http.ResponseWriter
	writer *gzip.Writer
}

func (g *gzipWriter) Write(data []byte) (int, error) {
	return g.writer.Write(data)
}

func GzipMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Add("Vary", "Accept-Encoding")
		if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
			next.ServeHTTP(w, r)
			return
		}
		w.Header().Set("Content-Encoding", "gzip")
		compressor := gzip.NewWriter(w)
		defer compressor.Close()
		next.ServeHTTP(&gzipWriter{ResponseWriter: w, writer: compressor}, r)
	})
}

func main() {
	mux := http.NewServeMux()
	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
		fmt.Fprintln(w, strings.Repeat("hello gzip ", 64))
	})
	_ = http.ListenAndServe(":8080", GzipMiddleware(mux))
}