package middleware import ( "bytes" "io" "net/http" "time" "api_yal/internal/logger" "github.com/go-chi/chi/v5/middleware" "go.uber.org/zap" ) // RequestLoggerMiddleware логирует все HTTP запросы func RequestLoggerMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { l := logger.Get() start := time.Now() // Создаем кастомный ResponseWriter для захвата статуса ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor) // Логируем тело запроса только для определенных методов (опционально) var body []byte if r.Method == "POST" || r.Method == "PUT" || r.Method == "PATCH" { body, _ = io.ReadAll(r.Body) r.Body = io.NopCloser(bytes.NewBuffer(body)) } // Обрабатываем запрос next.ServeHTTP(ww, r) // Логируем результат duration := time.Since(start) logFields := []zap.Field{ zap.String("method", r.Method), zap.String("path", r.URL.Path), zap.Int("status", ww.Status()), zap.Duration("duration", duration), zap.String("remote_addr", r.RemoteAddr), zap.String("user_agent", r.UserAgent()), } // Добавляем ID пользователя, если есть if userID, ok := GetUserID(r.Context()); ok { logFields = append(logFields, zap.Uint("user_id", userID)) } // Логируем тело запроса для ошибок if ww.Status() >= 400 && len(body) > 0 { logFields = append(logFields, zap.ByteString("request_body", body)) } // Выбираем уровень логирования в зависимости от статуса switch { case ww.Status() >= 500: l.Error("Request failed", logFields...) case ww.Status() >= 400: l.Warn("Request error", logFields...) default: l.Info("Request completed", logFields...) } }) }