Gzip large JSON API responses to cut transcript download time
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const gzipMin = 8 << 10
|
||||
|
||||
type gzipWriter struct {
|
||||
http.ResponseWriter
|
||||
held int
|
||||
gz *gzip.Writer
|
||||
}
|
||||
|
||||
func (w *gzipWriter) WriteHeader(status int) {
|
||||
if status == http.StatusOK && w.Header().Get("Content-Type") == "application/json" {
|
||||
w.held = status
|
||||
return
|
||||
}
|
||||
w.ResponseWriter.WriteHeader(status)
|
||||
}
|
||||
|
||||
func (w *gzipWriter) Write(b []byte) (int, error) {
|
||||
if w.held != 0 {
|
||||
if len(b) >= gzipMin {
|
||||
w.Header().Set("Content-Encoding", "gzip")
|
||||
w.Header().Del("Content-Length")
|
||||
w.gz = gzip.NewWriter(w.ResponseWriter)
|
||||
}
|
||||
w.ResponseWriter.WriteHeader(w.held)
|
||||
w.held = 0
|
||||
}
|
||||
if w.gz != nil {
|
||||
return w.gz.Write(b)
|
||||
}
|
||||
return w.ResponseWriter.Write(b)
|
||||
}
|
||||
|
||||
func (w *gzipWriter) Unwrap() http.ResponseWriter {
|
||||
return w.ResponseWriter
|
||||
}
|
||||
|
||||
func compress(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
gw := &gzipWriter{ResponseWriter: w}
|
||||
next.ServeHTTP(gw, r)
|
||||
if gw.held != 0 {
|
||||
w.WriteHeader(gw.held)
|
||||
}
|
||||
if gw.gz != nil {
|
||||
err := gw.gz.Close()
|
||||
if err != nil {
|
||||
slog.Warn("write response", "err", err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -135,7 +135,7 @@ func (s *Server) Handler() http.Handler {
|
||||
writeError(w, http.StatusBadRequest, err)
|
||||
},
|
||||
})
|
||||
return timing(http.NewCrossOriginProtection().Handler(mux))
|
||||
return timing(compress(http.NewCrossOriginProtection().Handler(mux)))
|
||||
}
|
||||
|
||||
func (s *Server) LoopbackHandler() http.Handler {
|
||||
|
||||
Reference in New Issue
Block a user