package handlers import ( "errors" "log/slog" "net/http" "github.com/gin-gonic/gin" "building-mgmt/internal/middleware" "building-mgmt/internal/repository" ) // respondError отдаёт JSON-ответ по классу ошибки репозитория. // // Тексты ошибок БД наружу не попадают: инфраструктурные ошибки // пишутся в лог и превращаются в 500, а на клиент уходят только // фиксированные сообщения. Если endpoint'у нужно своё сообщение, // он ветвится через errors.Is(...) сам, до вызова respondError. func respondError(c *gin.Context, err error) { // Общие атрибуты, чтобы ошибку можно было найти по запросу. attrs := []any{ "err", err, "request_id", middleware.RequestIDFrom(c), "method", c.Request.Method, "path", c.Request.URL.Path, } switch { case errors.Is(err, repository.ErrNotFound): c.JSON(http.StatusNotFound, gin.H{"error": "not found"}) case errors.Is(err, repository.ErrConflict): c.JSON(http.StatusConflict, gin.H{"error": "conflict"}) case errors.Is(err, repository.ErrInvalid): // Нарушение ограничения — это баг вызывающего кода, логируем. slog.Warn("constraint violation", attrs...) c.JSON(http.StatusUnprocessableEntity, gin.H{"error": "invalid request"}) default: slog.Error("internal error", attrs...) c.JSON(http.StatusInternalServerError, gin.H{"error": "internal server error"}) } }