Files
warpbox-dev/backend/libs/middleware/gzip.go

70 lines
1.5 KiB
Go
Raw Normal View History

package middleware
import (
"compress/gzip"
"io"
"net/http"
"strings"
)
type gzipResponseWriter struct {
http.ResponseWriter
writer io.Writer
wrote bool
}
func (w *gzipResponseWriter) WriteHeader(status int) {
if w.wrote {
return
}
w.wrote = true
header := w.Header()
header.Del("Content-Length")
header.Del("Accept-Ranges")
header.Set("Content-Encoding", "gzip")
header.Add("Vary", "Accept-Encoding")
w.ResponseWriter.WriteHeader(status)
}
func (w *gzipResponseWriter) Write(data []byte) (int, error) {
if !w.wrote {
w.WriteHeader(http.StatusOK)
}
return w.writer.Write(data)
}
func Gzip(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !acceptsGzip(r) || shouldSkipGzip(r) {
next.ServeHTTP(w, r)
return
}
gz := gzip.NewWriter(w)
defer gz.Close()
next.ServeHTTP(&gzipResponseWriter{
ResponseWriter: w,
writer: gz,
}, r)
})
}
func acceptsGzip(r *http.Request) bool {
return strings.Contains(r.Header.Get("Accept-Encoding"), "gzip")
}
func shouldSkipGzip(r *http.Request) bool {
if r.Method == http.MethodHead || r.Header.Get("Range") != "" {
return true
}
path := r.URL.Path
switch ext := strings.ToLower(path[strings.LastIndex(path, ".")+1:]); ext {
case "br", "gz", "zip", "7z", "rar", "jpg", "jpeg", "png", "gif", "webp", "avif", "mp4", "webm", "mov", "m4v", "mp3", "ogg", "woff", "woff2", "ttf", "otf":
return true
default:
return false
}
}