package middleware import ( "net/http" "net/http/httptest" "testing" "github.com/gin-gonic/gin" ) func TestCacheHeaders(t *testing.T) { gin.SetMode(gin.TestMode) cfg := DefaultCacheHeadersConfig() tests := []struct { name string path string expectedHeader string }{ { name: "static assets get immutable cache", path: "/static/js/main.abc123.js", expectedHeader: "public, max-age=31536000, immutable", }, { name: "audio files get 7 day cache", path: "/audio/track-123/file.mp3", expectedHeader: "public, max-age=604800", }, { name: "HLS segments get short cache", path: "/hls/track-123/segment.ts", expectedHeader: "public, max-age=60", }, { name: "images get 30 day cache", path: "/images/covers/album.webp", expectedHeader: "public, max-age=2592000", }, { name: "API responses no-cache", path: "/api/v1/tracks", expectedHeader: "no-cache, no-store, must-revalidate", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { router := gin.New() router.Use(CacheHeaders(cfg)) router.GET(tt.path, func(c *gin.Context) { c.String(200, "ok") }) w := httptest.NewRecorder() req, _ := http.NewRequest("GET", tt.path, nil) router.ServeHTTP(w, req) got := w.Header().Get("Cache-Control") if got != tt.expectedHeader { t.Errorf("path %s: expected Cache-Control=%q, got %q", tt.path, tt.expectedHeader, got) } }) } } func TestDefaultCacheHeadersConfig(t *testing.T) { cfg := DefaultCacheHeadersConfig() if len(cfg.Rules) == 0 { t.Error("expected non-empty default rules") } // Verify critical rules exist hasStatic := false hasAudio := false hasAPI := false for _, rule := range cfg.Rules { switch rule.PathPrefix { case "/static/": hasStatic = true if !rule.Immutable { t.Error("static assets should be immutable") } case "/audio/": hasAudio = true if rule.MaxAge != 604800 { t.Errorf("audio max-age should be 604800, got %d", rule.MaxAge) } case "/api/": hasAPI = true if rule.Directive != "no-cache" { t.Errorf("API directive should be no-cache, got %s", rule.Directive) } } } if !hasStatic { t.Error("missing static rule") } if !hasAudio { t.Error("missing audio rule") } if !hasAPI { t.Error("missing API rule") } }