package middleware import ( "log/slog" "net/http" "net/http/httptest" "testing" "sneak.berlin/go/pixa/internal/config" ) func TestSecurityHeaders(t *testing.T) { // Create middleware instance cfg := &config.Config{} mw := &Middleware{ log: slog.Default(), config: cfg, } // Create a test handler testHandler := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) }) // Wrap with security headers middleware handler := mw.SecurityHeaders()(testHandler) // Make a test request req := httptest.NewRequest(http.MethodGet, "/test", nil) rec := httptest.NewRecorder() handler.ServeHTTP(rec, req) // Check security headers tests := []struct { header string want string }{ {"X-Content-Type-Options", "nosniff"}, {"X-Frame-Options", "DENY"}, {"Referrer-Policy", "strict-origin-when-cross-origin"}, {"X-XSS-Protection", "0"}, } for _, tt := range tests { t.Run(tt.header, func(t *testing.T) { got := rec.Header().Get(tt.header) if got != tt.want { t.Errorf("%s = %q, want %q", tt.header, got, tt.want) } }) } } func TestSecurityHeaders_PreservesExistingHeaders(t *testing.T) { cfg := &config.Config{} mw := &Middleware{ log: slog.Default(), config: cfg, } // Handler that sets its own headers testHandler := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("X-Custom-Header", "custom-value") w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) }) handler := mw.SecurityHeaders()(testHandler) req := httptest.NewRequest(http.MethodGet, "/test", nil) rec := httptest.NewRecorder() handler.ServeHTTP(rec, req) // Security headers should be present if rec.Header().Get("X-Content-Type-Options") != "nosniff" { t.Error("X-Content-Type-Options not set") } // Custom headers should still be there if rec.Header().Get("X-Custom-Header") != "custom-value" { t.Error("Custom header was overwritten") } if rec.Header().Get("Content-Type") != "application/json" { t.Error("Content-Type was overwritten") } }