68 lines
1.6 KiB
Go
68 lines
1.6 KiB
Go
package errors
|
||
|
||
import (
|
||
"fmt"
|
||
"net/http"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
"github.com/google/uuid"
|
||
log "github.com/sirupsen/logrus"
|
||
)
|
||
|
||
// ErrorHandlerMiddleware 是一个 Gin 中间件,用于统一处理请求过程中的错误
|
||
// 它会为每个请求生成一个唯一的请求 ID,并在错误发生时将其添加到错误响应中
|
||
func ErrorHandlerMiddleware() gin.HandlerFunc {
|
||
return func(c *gin.Context) {
|
||
// 生成请求 ID
|
||
requestID := uuid.New().String()
|
||
c.Set("RequestID", requestID)
|
||
c.Header("X-Request-ID", requestID)
|
||
|
||
// 处理请求
|
||
c.Next()
|
||
|
||
// 检查是否有错误
|
||
if len(c.Errors) > 0 {
|
||
// 获取第一个错误
|
||
err := c.Errors[0].Err
|
||
|
||
// 使用 Err 函数处理错误响应
|
||
Err(c, err)
|
||
|
||
// 已经处理过错误,不需要继续
|
||
c.Abort()
|
||
}
|
||
}
|
||
}
|
||
|
||
// RecoveryMiddleware 是一个 Gin 中间件,用于从 panic 恢复并返回 500 错误
|
||
func RecoveryMiddleware() gin.HandlerFunc {
|
||
return func(c *gin.Context) {
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
// 获取请求 ID
|
||
requestID, _ := c.Get("RequestID")
|
||
requestIDStr, _ := requestID.(string)
|
||
|
||
// 创建内部服务器错误
|
||
var err *AppError
|
||
switch v := r.(type) {
|
||
case error:
|
||
err = Internal("panic recovered", v).WithRequestID(requestIDStr)
|
||
default:
|
||
err = Internal(fmt.Sprintf("panic recovered: %v", r), nil).WithRequestID(requestIDStr)
|
||
}
|
||
|
||
// 记录错误日志
|
||
log.Errorf("PANIC RECOVERED: %v\n", err)
|
||
|
||
// 返回 500 错误
|
||
c.JSON(http.StatusInternalServerError, err)
|
||
c.Abort()
|
||
}
|
||
}()
|
||
|
||
c.Next()
|
||
}
|
||
}
|