// // recover_log.go // Copyright (C) 2022 tiglog // // Distributed under terms of the MIT license. // package middleware import ( "net" "net/http" "net/http/httputil" "os" "strings" "git.hexq.cn/tiglog/golib/helper" "git.hexq.cn/tiglog/golib/logger" "github.com/gin-gonic/gin" ) func GinRecover() gin.HandlerFunc { var log = logger.Recover() return func(c *gin.Context) { defer func() { if err := recover(); err != nil { // Check for a broken connection, as it is not really a // condition that warrants a panic stack trace. var brokenPipe bool if ne, ok := err.(*net.OpError); ok { if se, ok := ne.Err.(*os.SyscallError); ok { if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") { brokenPipe = true } } } httpRequest, _ := httputil.DumpRequest(c.Request, false) if brokenPipe { log.Error().Err(err.(error)).Str("request", string(httpRequest)). Msg(c.Request.URL.Path) // If the connection is dead, we can't write a status to it. c.Error(err.(error)) // nolint: errcheck c.Abort() return } var er = err.(error) log.Error().Str("request", string(httpRequest)). Err(helper.WrapErr(er, "wrap")).Msg("Recovery from panic") c.AbortWithError(http.StatusInternalServerError, er) } }() c.Next() } }