Procházet zdrojové kódy

fix: Panic Recovery

runningwater před 8 měsíci
rodič
revize
fa9b9a27cd
2 změnil soubory, kde provedl 65 přidání a 1 odebrání
  1. 64 0
      app/http/middlewares/recovery.go
  2. 1 1
      bootstrap/route.go

+ 64 - 0
app/http/middlewares/recovery.go

@@ -0,0 +1,64 @@
+package middlewares
+
+import (
+	"net"
+	"net/http"
+	"net/http/httputil"
+	"os"
+	"strings"
+	"time"
+
+	"github.com/gin-gonic/gin"
+	"github.com/runningwater/gohub/pkg/logger"
+	"go.uber.org/zap"
+)
+
+// Recovery 使用 zap.Error() 来记录 panic 和 call stack
+func Recovery() gin.HandlerFunc {
+
+	return func(c *gin.Context) {
+		defer func() {
+			if err := recover(); err != nil {
+				
+				// 获取用户的请求信息
+				httpRquest, _ := httputil.DumpRequest(c.Request, true)
+
+				// 链接中断,客户端中断连接为正常行为,不需要记录堆栈信息
+				var brokenPipe bool
+				if ne, ok := err.(*net.OpError); ok {
+					if se, ok := ne.Err.(*os.SyscallError); ok {
+						errStr := strings.ToLower(se.Error())
+						if strings.Contains(errStr, "broken pipe") || strings.Contains(errStr, "connection reset by peer") {
+							brokenPipe = true
+						}
+					}
+				}
+				// 链接中断的情况
+				if brokenPipe {
+					logger.Error(c.Request.URL.Path,
+						zap.Time("time", time.Now()),
+						zap.Any("error", err),
+						zap.String("request", string(httpRquest)),
+					)
+					c.Error(err.(error))
+					c.Abort()
+					// 链接已断开,无法写状态
+					return
+				}
+				// 如果不是链接中断的情况,记录堆栈信息
+				logger.Error("[Recovery from panic]",
+					zap.Time("time", time.Now()), // 记录当前时间
+					zap.Any("error", err), // 记录错误信息
+					zap.String("request", string(httpRquest)), // 记录请求信息
+					zap.Stack("stack"), // 记录堆栈信息
+				)
+				c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
+					"message": "服务器内部错误,请稍后再试",
+				})
+			}
+		}()
+
+		// 继续处理请求
+		c.Next()
+	}
+}

+ 1 - 1
bootstrap/route.go

@@ -41,6 +41,6 @@ func setup404Handler(router *gin.Engine) {
 func registerGlobalMiddleWare(router *gin.Engine) {
 	router.Use(
 		middlewares.Logger(),
-		gin.Recovery(),
+		middlewares.Recovery(),
 	)
 }