package api import ( "log" "net/http" ) // logRequests логирует метод и путь каждого входящего запроса. // Middleware-обёртка: оборачивает любой http.Handler. func logRequests(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { log.Printf("%s %s", r.Method, r.URL.Path) next.ServeHTTP(w, r) }) } // withCORS добавляет CORS заголовки для разрешения cross-origin запросов. // // Почему Access-Control-Allow-Origin: *: // Console — одностраничное приложение, может обслуживаться с любого домена. // Строгий CORS с конкретным Origin потребовал бы конфигурации при деплое. // Все чувствительные операции защищены X-Auth-Token — не cookie, не ambient credentials. func withCORS(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Methods", "GET,POST,PUT,PATCH,DELETE,OPTIONS") w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Auth-Token, X-Auth-Env") // Preflight OPTIONS — отвечаем сразу без передачи в handler if r.Method == http.MethodOptions { w.WriteHeader(http.StatusNoContent) return } next.ServeHTTP(w, r) }) } // withSecurityHeaders добавляет стандартные HTTP security заголовки. // Снижает риск XSS, clickjacking и утечки Referer. func withSecurityHeaders(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // nosniff: браузер не должен угадывать MIME тип — только то что в Content-Type w.Header().Set("X-Content-Type-Options", "nosniff") // DENY: запрещаем отображение страницы в iframe (clickjacking protection) w.Header().Set("X-Frame-Options", "DENY") // strict-origin-when-cross-origin: скрываем полный URL при cross-origin запросах w.Header().Set("Referrer-Policy", "strict-origin-when-cross-origin") // Отключаем браузерные API которые не нужны console w.Header().Set("Permissions-Policy", "camera=(), microphone=(), geolocation=()") // CSP: разрешаем только ресурсы с того же origin + inline scripts/styles (нужны для embedded UI) w.Header().Set("Content-Security-Policy", "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; "+ "img-src 'self' data:; connect-src 'self'; font-src 'self' data:; object-src 'none'; "+ "frame-ancestors 'none'; base-uri 'self'; form-action 'self'; upgrade-insecure-requests; block-all-mixed-content") next.ServeHTTP(w, r) }) }