go 56 lines · 7 steps

How gzip HTTP middleware works in Go

A net/http middleware that compresses responses on the fly while pooling gzip writers to avoid per-request allocations.

Explained by highlit
1package middleware
2 
3import (
4 "compress/gzip"
5 "io"
6 "net/http"
7 "strings"
8 "sync"
9)
10 
11var gzipPool = sync.Pool{
12 New: func() any {
13 return gzip.NewWriter(io.Discard)
14 },
15}
16 
17type gzipResponseWriter struct {
18 http.ResponseWriter
19 gw *gzip.Writer
20}
21 
22func (w *gzipResponseWriter) Write(b []byte) (int, error) {
23 if w.Header().Get("Content-Type") == "" {
24 w.Header().Set("Content-Type", http.DetectContentType(b))
25 }
26 return w.gw.Write(b)
27}
28 
29func (w *gzipResponseWriter) Flush() {
30 _ = w.gw.Flush()
31 if f, ok := w.ResponseWriter.(http.Flusher); ok {
32 f.Flush()
33 }
34}
35 
36func Gzip(next http.Handler) http.Handler {
37 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
38 if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
39 next.ServeHTTP(w, r)
40 return
41 }
42 
43 gw := gzipPool.Get().(*gzip.Writer)
44 gw.Reset(w)
45 defer func() {
46 _ = gw.Close()
47 gzipPool.Put(gw)
48 }()
49 
50 w.Header().Set("Content-Encoding", "gzip")
51 w.Header().Add("Vary", "Accept-Encoding")
52 w.Header().Del("Content-Length")
53 
54 next.ServeHTTP(&gzipResponseWriter{ResponseWriter: w, gw: gw}, r)
55 })
56}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Embedding http.ResponseWriter lets you override just Write while inheriting the rest of the interface for free.
  2. 2sync.Pool recycles expensive objects like gzip writers so high-traffic handlers avoid constant allocation.
  3. 3Compression middleware must negotiate via Accept-Encoding and fix up headers like Content-Encoding and Content-Length.

Related explainers

Share this explainer

Here's the card — post it anywhere.

How gzip HTTP middleware works in Go — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code