axe/internal/handlers/httperr.go

43 lines
1.6 KiB
Go
Raw Permalink Normal View History

2026-10-18 19:07:25 +00:00
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"})
}
}