feat: initialize warpbox.dev project structure and backend
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.
This commit is contained in:
69
backend/libs/middleware/gzip.go
Normal file
69
backend/libs/middleware/gzip.go
Normal file
@@ -0,0 +1,69 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user