package handlers import ( "net/http" "os" "path/filepath" "strings" ) func (a *App) Static() http.Handler { fileServer := http.StripPrefix("/static/", http.FileServer(http.Dir(a.cfg.StaticDir))) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { setStaticCacheHeaders(w, r.URL.Path) fileServer.ServeHTTP(w, r) }) } func (a *App) EmojiAsset(w http.ResponseWriter, r *http.Request) { pack := strings.TrimSpace(r.PathValue("pack")) file := strings.TrimSpace(r.PathValue("file")) if pack == "" || file == "" || strings.Contains(pack, "/") || strings.Contains(pack, "\\") || strings.Contains(pack, "..") || strings.Contains(file, "/") || strings.Contains(file, "\\") || strings.Contains(file, "..") || !isEmojiFile(file) { http.NotFound(w, r) return } path := filepath.Join(a.emojiRoot(), pack, file) info, err := os.Stat(path) if err != nil || info.IsDir() { http.NotFound(w, r) return } setStaticCacheHeaders(w, r.URL.Path) http.ServeFile(w, r, path) } func (a *App) ServiceWorker(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/javascript; charset=utf-8") w.Header().Set("Cache-Control", "public, max-age=86400") w.Header().Set("Service-Worker-Allowed", "/") http.ServeFile(w, r, filepath.Join(a.cfg.StaticDir, "js", "service-worker.js")) } func (a *App) ShareTargetFallback(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/?share-target=unsupported", http.StatusSeeOther) } func setStaticCacheHeaders(w http.ResponseWriter, path string) { ext := strings.ToLower(filepath.Ext(path)) switch ext { case ".avif", ".gif", ".ico", ".jpg", ".jpeg", ".png", ".svg", ".webp", ".mp4", ".m4v", ".mov", ".webm", ".mp3", ".ogg", ".eot", ".otf", ".ttf", ".woff", ".woff2": w.Header().Set("Cache-Control", "public, max-age=31536000, immutable") case ".css", ".js": w.Header().Set("Cache-Control", "public, max-age=86400") default: w.Header().Set("Cache-Control", "public, max-age=3600") } }