Initialize the repository with the core Go backend architecture and a frontend mockup for warpbox.dev, a self-hosted file-sharing application. - Set up Go backend modules for configuration, HTTP server, middleware, handlers, and templates. - Add local development scripts, environment templates, and basic project configuration. - Include a React-based frontend mockup under the docs directory.
70 lines
1.5 KiB
Go
70 lines
1.5 KiB
Go
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
|
|
}
|
|
}
|