webui: delete non-gzip'd assets

Reduces webui assets from 83M to 16M.
Almost all browsers support gzip.
For those that don't, we provide on-the-fly decompression.

Co-Authored-By: sketch <hello@sketch.dev>
Change-ID: sbc10790564044d6bk
diff --git a/loop/server/gzhandler/gzhandler.go b/loop/server/gzhandler/gzhandler.go
index 3109ea2..6658db2 100644
--- a/loop/server/gzhandler/gzhandler.go
+++ b/loop/server/gzhandler/gzhandler.go
@@ -3,6 +3,7 @@
 package gzhandler
 
 import (
+	"compress/gzip"
 	"io"
 	"io/fs"
 	"mime"
@@ -26,61 +27,73 @@
 
 // ServeHTTP serves a file with special handling for pre-compressed .gz files
 func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-	// Clean and prepare the URL path
 	urlPath := r.URL.Path
 	if !strings.HasPrefix(urlPath, "/") {
 		urlPath = "/" + urlPath
 	}
 	urlPath = path.Clean(urlPath)
 
-	// Check if client accepts gzip encoding
-	acceptEncoding := r.Header.Get("Accept-Encoding")
-	acceptsGzip := strings.Contains(acceptEncoding, "gzip")
-
 	// Check if the file itself is not a gzip file (we don't want to double-compress)
 	isCompressibleFile := !strings.HasSuffix(urlPath, ".gz")
-
-	if acceptsGzip && isCompressibleFile {
-		// Try to open the gzipped version of the file
-		gzPath := urlPath + ".gz"
-		gzFile, err := h.root.Open(gzPath)
-
-		if err == nil {
-			defer gzFile.Close()
-
-			// Get file info to check if it's a regular file
-			gzStat, err := gzFile.Stat()
-			if err != nil || gzStat.IsDir() {
-				// Not a valid file, fall back to normal serving
-				http.FileServer(h.root).ServeHTTP(w, r)
-				return
-			}
-
-			// Determine the content type based on the original file (not the .gz)
-			contentType := mime.TypeByExtension(path.Ext(urlPath))
-			if contentType == "" {
-				contentType = "application/octet-stream"
-			}
-
-			// Set the appropriate headers for serving gzipped content
-			w.Header().Set("Content-Type", contentType)
-			w.Header().Set("Content-Encoding", "gzip")
-			w.Header().Set("Vary", "Accept-Encoding")
-
-			// Read the gzipped file into memory to avoid 'seeker can't seek' error
-			gzippedData, err := io.ReadAll(gzFile)
-			if err != nil {
-				http.Error(w, "Error reading gzipped content", http.StatusInternalServerError)
-				return
-			}
-
-			// Write the headers and gzipped content
-			w.WriteHeader(http.StatusOK)
-			w.Write(gzippedData)
-			return
-		}
+	if !isCompressibleFile {
+		// Fall back to regular serving.
+		http.FileServer(h.root).ServeHTTP(w, r)
+		return
 	}
 
-	// Fall back to standard file serving if gzipped version not found or not applicable
-	http.FileServer(h.root).ServeHTTP(w, r)
+	// Try to open the gzipped version of the file
+	gzPath := urlPath + ".gz"
+	gzFile, err := h.root.Open(gzPath)
+	if err != nil {
+		// Fall back to regular serving.
+		http.FileServer(h.root).ServeHTTP(w, r)
+		return
+	}
+	defer gzFile.Close()
+
+	// Fall back to regular serving for directories (how would this even happen?)
+	gzStat, err := gzFile.Stat()
+	if err != nil || gzStat.IsDir() {
+		// Not a valid file, fall back to normal serving
+		http.FileServer(h.root).ServeHTTP(w, r)
+		return
+	}
+
+	// Determine the content type based on the original file (not the .gz)
+	contentType := mime.TypeByExtension(path.Ext(urlPath))
+	if contentType == "" {
+		contentType = "application/octet-stream"
+	}
+
+	acceptsGzip := strings.Contains(r.Header.Get("Accept-Encoding"), "gzip")
+	if acceptsGzip {
+		w.Header().Set("Content-Type", contentType)
+		w.Header().Set("Content-Encoding", "gzip")
+		w.Header().Set("Vary", "Accept-Encoding")
+
+		// Read the gzipped file into memory to avoid 'seeker can't seek' error
+		gzippedData, err := io.ReadAll(gzFile)
+		if err != nil {
+			http.Error(w, "Error reading gzipped content", http.StatusInternalServerError)
+			return
+		}
+
+		// Write the headers and gzipped content
+		w.WriteHeader(http.StatusOK)
+		w.Write(gzippedData)
+		return
+	}
+
+	// No gzip support; decompress for them.
+
+	// Decompress the .gz file and serve it uncompressed
+	gzReader, err := gzip.NewReader(gzFile)
+	if err != nil {
+		http.FileServer(h.root).ServeHTTP(w, r)
+		return
+	}
+	defer gzReader.Close()
+	w.Header().Set("Content-Type", contentType)
+	w.WriteHeader(http.StatusOK)
+	io.Copy(w, gzReader)
 }