github.com/wfusion/gofusion@v1.1.14/http/middleware/recover.go (about)

     1  package middleware
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"net"
     7  	"net/http"
     8  	"os"
     9  	"runtime/debug"
    10  	"strings"
    11  	"time"
    12  
    13  	"github.com/gin-gonic/gin"
    14  	"github.com/go-resty/resty/v2"
    15  	"golang.org/x/text/language"
    16  
    17  	"github.com/wfusion/gofusion/common/constant"
    18  	"github.com/wfusion/gofusion/common/utils"
    19  	"github.com/wfusion/gofusion/i18n"
    20  
    21  	fusCtx "github.com/wfusion/gofusion/context"
    22  )
    23  
    24  func Recover(appName string, logger resty.Logger, errMsg map[string]any) gin.HandlerFunc {
    25  	tag := i18n.DefaultLang(i18n.AppName(appName))
    26  	return func(c *gin.Context) {
    27  		defer func() {
    28  			if err := recover(); err != nil {
    29  				// Check for a broken connection, as it is not really a
    30  				// condition that warrants a panic stack trace.
    31  				var brokenPipe bool
    32  				if ne, ok := err.(*net.OpError); ok {
    33  					if se, ok := ne.Err.(*os.SyscallError); ok {
    34  						if strings.Contains(strings.ToLower(se.Error()), "broken pipe") ||
    35  							strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") {
    36  							brokenPipe = true
    37  						}
    38  					}
    39  				}
    40  				if brokenPipe {
    41  					c.Abort()
    42  					return
    43  				}
    44  				debugStack := ""
    45  				for _, v := range strings.Split(string(debug.Stack()), "\n") {
    46  					debugStack += "> " + v + "\n"
    47  				}
    48  				hostname, hostnameErr := os.Hostname()
    49  				if hostnameErr != nil {
    50  					hostname = "unknown"
    51  				}
    52  				buffer, cb := utils.BytesBufferPool.Get(nil)
    53  				defer cb()
    54  
    55  				if tag == language.Chinese {
    56  					buffer.WriteString(fmt.Sprintf("%v \n", err))
    57  					buffer.WriteString(fmt.Sprintf("请求时间:%v \n", time.Now().Format(constant.StdTimeLayout)))
    58  					buffer.WriteString(fmt.Sprintf("主机名称:%v \n", hostname))
    59  					buffer.WriteString(fmt.Sprintf("请求编号:%v \n", c.GetString(fusCtx.KeyTraceID)))
    60  					buffer.WriteString(fmt.Sprintf("请求地址:%v \n",
    61  						c.Request.Method+"  "+c.Request.Host+c.Request.RequestURI))
    62  					buffer.WriteString(fmt.Sprintf("请求UA:%v \n", c.Request.UserAgent()))
    63  					buffer.WriteString(fmt.Sprintf("请求IP:%v \n", c.ClientIP()))
    64  					buffer.WriteString(fmt.Sprintf("异常捕获:\n%v", debugStack))
    65  				} else {
    66  					buffer.WriteString(fmt.Sprintf("%v \n", err))
    67  					buffer.WriteString(fmt.Sprintf("RequstTime:%v \n", time.Now().Format(constant.StdTimeLayout)))
    68  					buffer.WriteString(fmt.Sprintf("Hostname:%v \n", hostname))
    69  					buffer.WriteString(fmt.Sprintf("TraceID:%v \n", c.GetString(fusCtx.KeyTraceID)))
    70  					buffer.WriteString(fmt.Sprintf("RequestURI:%v \n",
    71  						c.Request.Method+"  "+c.Request.Host+c.Request.RequestURI))
    72  					buffer.WriteString(fmt.Sprintf("UA:%v \n", c.Request.UserAgent()))
    73  					buffer.WriteString(fmt.Sprintf("IP:%v \n", c.ClientIP()))
    74  					buffer.WriteString(fmt.Sprintf("ErrorStack:\n%v", debugStack))
    75  				}
    76  
    77  				if logger != nil {
    78  					logger.Errorf(buffer.String(), fusCtx.New(fusCtx.Gin(c)))
    79  				} else {
    80  					log.Printf(buffer.String())
    81  				}
    82  
    83  				c.AbortWithStatusJSON(http.StatusInternalServerError, errMsg)
    84  			}
    85  		}()
    86  		c.Next()
    87  	}
    88  }