package httpserver import ( "net/http" "strings" "update_server/internal/config" ) const contentSecurityPolicy = "default-src 'self'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' data:; object-src 'none'; script-src 'self'; style-src 'self'" func securityHeaders(cfg config.Config) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { headers := w.Header() headers.Set("Content-Security-Policy", contentSecurityPolicy) headers.Set("Cross-Origin-Opener-Policy", "same-origin") headers.Set("Cross-Origin-Resource-Policy", "same-origin") headers.Set("Permissions-Policy", "camera=(), geolocation=(), microphone=()") headers.Set("Referrer-Policy", "no-referrer") headers.Set("X-Content-Type-Options", "nosniff") headers.Set("X-Frame-Options", "DENY") if cfg.SecureCookies { headers.Set("Strict-Transport-Security", "max-age=31536000") } next.ServeHTTP(w, r) }) } } func adminResponseHeaders(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { applyNoStoreHeaders(w) addVaryHeader(w, "Cookie") w.Header().Set("X-Robots-Tag", "noindex, nofollow") next.ServeHTTP(w, r) }) } func apiResponseHeaders(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("X-Robots-Tag", "noindex, nofollow") next.ServeHTTP(w, r) }) } func protectedAPIResponseHeaders(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { applyNoStoreHeaders(w) addVaryHeader(w, "Authorization") w.Header().Set("X-Robots-Tag", "noindex, nofollow") next.ServeHTTP(w, r) }) } func applyNoStoreHeaders(w http.ResponseWriter) { w.Header().Set("Cache-Control", "no-store, private, max-age=0") w.Header().Set("Pragma", "no-cache") w.Header().Set("Expires", "0") } func addVaryHeader(w http.ResponseWriter, value string) { value = strings.TrimSpace(value) if value == "" { return } current := w.Header().Values("Vary") for _, entry := range current { for _, existing := range strings.Split(entry, ",") { if strings.EqualFold(strings.TrimSpace(existing), value) { return } } } w.Header().Add("Vary", value) }