chore: stabilize lint and verify builds
This commit is contained in:
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/gofiber/fiber/v3/binder"
|
||||
"github.com/gofiber/utils/v2"
|
||||
"github.com/google/uuid"
|
||||
log "github.com/sirupsen/logrus"
|
||||
logrus "github.com/sirupsen/logrus"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"quyun/v2/database/models"
|
||||
@@ -28,18 +28,22 @@ func NewResponseSender() *ResponseSender {
|
||||
}
|
||||
|
||||
// SendError 发送错误响应
|
||||
func (s *ResponseSender) SendError(ctx fiber.Ctx, err error) error {
|
||||
appErr := s.handler.Handle(err)
|
||||
func (sender *ResponseSender) SendError(ctx fiber.Ctx, err error) error {
|
||||
appErr := sender.handler.Handle(err)
|
||||
|
||||
if appErr == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 记录错误日志
|
||||
s.logError(appErr, ctx)
|
||||
sender.logError(appErr, ctx)
|
||||
|
||||
// 根据 Content-Type 返回不同格式
|
||||
return s.sendResponse(ctx, appErr)
|
||||
return sender.sendResponse(ctx, appErr)
|
||||
}
|
||||
|
||||
// logError 记录错误日志
|
||||
func (s *ResponseSender) logError(appErr *AppError, ctx fiber.Ctx) {
|
||||
func (sender *ResponseSender) logError(appErr *AppError, ctx fiber.Ctx) {
|
||||
// 确保每个错误实例都有唯一ID,便于日志关联
|
||||
if appErr.ID == "" {
|
||||
appErr.ID = uuid.NewString()
|
||||
@@ -47,44 +51,48 @@ func (s *ResponseSender) logError(appErr *AppError, ctx fiber.Ctx) {
|
||||
|
||||
// 构造详细的错误级联链路(包含类型、状态、定位等)
|
||||
chain := make([]map[string]any, 0, 4)
|
||||
var e error = appErr
|
||||
for e != nil {
|
||||
currentErr := error(appErr)
|
||||
for currentErr != nil {
|
||||
entry := map[string]any{
|
||||
"type": fmt.Sprintf("%T", e),
|
||||
"error": e.Error(),
|
||||
"type": fmt.Sprintf("%T", currentErr),
|
||||
"error": currentErr.Error(),
|
||||
}
|
||||
switch v := e.(type) {
|
||||
case *AppError:
|
||||
entry["code"] = v.Code
|
||||
entry["statusCode"] = v.StatusCode
|
||||
if v.file != "" {
|
||||
entry["file"] = v.file
|
||||
|
||||
var appErrItem *AppError
|
||||
if errors.As(currentErr, &appErrItem) {
|
||||
entry["code"] = appErrItem.Code
|
||||
entry["statusCode"] = appErrItem.StatusCode
|
||||
if appErrItem.file != "" {
|
||||
entry["file"] = appErrItem.file
|
||||
}
|
||||
if len(v.params) > 0 {
|
||||
entry["params"] = v.params
|
||||
if len(appErrItem.params) > 0 {
|
||||
entry["params"] = appErrItem.params
|
||||
}
|
||||
if v.sql != "" {
|
||||
entry["sql"] = v.sql
|
||||
if appErrItem.sql != "" {
|
||||
entry["sql"] = appErrItem.sql
|
||||
}
|
||||
if v.ID != "" {
|
||||
entry["id"] = v.ID
|
||||
if appErrItem.ID != "" {
|
||||
entry["id"] = appErrItem.ID
|
||||
}
|
||||
case *fiber.Error:
|
||||
entry["statusCode"] = v.Code
|
||||
entry["message"] = v.Message
|
||||
}
|
||||
|
||||
var fiberErr *fiber.Error
|
||||
if errors.As(currentErr, &fiberErr) {
|
||||
entry["statusCode"] = fiberErr.Code
|
||||
entry["message"] = fiberErr.Message
|
||||
}
|
||||
|
||||
// GORM 常见错误归类标记
|
||||
if errors.Is(e, gorm.ErrRecordNotFound) {
|
||||
if errors.Is(currentErr, gorm.ErrRecordNotFound) {
|
||||
entry["gorm"] = "record_not_found"
|
||||
} else if errors.Is(e, gorm.ErrDuplicatedKey) {
|
||||
} else if errors.Is(currentErr, gorm.ErrDuplicatedKey) {
|
||||
entry["gorm"] = "duplicated_key"
|
||||
} else if errors.Is(e, gorm.ErrInvalidTransaction) {
|
||||
} else if errors.Is(currentErr, gorm.ErrInvalidTransaction) {
|
||||
entry["gorm"] = "invalid_transaction"
|
||||
}
|
||||
|
||||
chain = append(chain, entry)
|
||||
e = errors.Unwrap(e)
|
||||
currentErr = errors.Unwrap(currentErr)
|
||||
}
|
||||
|
||||
root := chain[len(chain)-1]["error"]
|
||||
@@ -100,7 +108,7 @@ func (s *ResponseSender) logError(appErr *AppError, ctx fiber.Ctx) {
|
||||
fullPath = fmt.Sprintf("%s?%s", path, query)
|
||||
}
|
||||
|
||||
fields := log.Fields{
|
||||
fields := logrus.Fields{
|
||||
"id": appErr.ID,
|
||||
"code": appErr.Code,
|
||||
"statusCode": appErr.StatusCode,
|
||||
@@ -131,7 +139,7 @@ func (s *ResponseSender) logError(appErr *AppError, ctx fiber.Ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
logEntry := log.WithFields(fields)
|
||||
logEntry := logrus.WithFields(fields)
|
||||
|
||||
if appErr.originalErr != nil {
|
||||
logEntry = logEntry.WithError(appErr.originalErr)
|
||||
@@ -148,16 +156,28 @@ func (s *ResponseSender) logError(appErr *AppError, ctx fiber.Ctx) {
|
||||
}
|
||||
|
||||
// sendResponse 发送响应
|
||||
func (s *ResponseSender) sendResponse(ctx fiber.Ctx, appErr *AppError) error {
|
||||
func (sender *ResponseSender) sendResponse(ctx fiber.Ctx, appErr *AppError) error {
|
||||
contentType := utils.ToLower(utils.UnsafeString(ctx.Request().Header.ContentType()))
|
||||
contentType = binder.FilterFlags(utils.ParseVendorSpecificContentType(contentType))
|
||||
|
||||
switch contentType {
|
||||
case fiber.MIMETextXML, fiber.MIMEApplicationXML:
|
||||
return ctx.Status(appErr.StatusCode).XML(appErr)
|
||||
if err := ctx.Status(appErr.StatusCode).XML(appErr); err != nil {
|
||||
return fmt.Errorf("send xml response: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
case fiber.MIMETextHTML, fiber.MIMETextPlain:
|
||||
return ctx.Status(appErr.StatusCode).SendString(appErr.Message)
|
||||
if err := ctx.Status(appErr.StatusCode).SendString(appErr.Message); err != nil {
|
||||
return fmt.Errorf("send text response: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
default:
|
||||
return ctx.Status(appErr.StatusCode).JSON(appErr)
|
||||
if err := ctx.Status(appErr.StatusCode).JSON(appErr); err != nil {
|
||||
return fmt.Errorf("send json response: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user