package main import ( "log/slog" "net" "net/http" "net/http/httputil" "os" "runtime/debug" "strings" "time" "go.uber.org/zap" "joylink.club/bj-rtsts-server/db/dbquery" "joylink.club/bj-rtsts-server/dto" "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" sloggin "github.com/samber/slog-gin" "joylink.club/bj-rtsts-server/config" "joylink.club/bj-rtsts-server/db" "joylink.club/bj-rtsts-server/logger" ) func InitServer() *gin.Engine { config.LoadConfig() err := logger.InitLogger() if err != nil { panic(err) } err = db.InitDb() if err != nil { panic(err) } dbquery.SetDefault(db.DB) engine := gin.New() conf := cors.DefaultConfig() conf.AllowHeaders = []string{"*"} conf.AllowAllOrigins = true // engine.Use(ginzap.Ginzap(zap.L(), time.DateTime, false)) engine.Use(sloggin.New(slog.Default())) engine.Use(cors.New(conf)) // gin panic 异常处理,默认处理为 engine.Use(CustomRecoveryWithSlog(slog.Default(), true, func(c *gin.Context, e interface{}) { switch e := e.(type) { case error: c.JSON(http.StatusInternalServerError, &dto.ErrorDto{ Code: dto.LogicError, Tip: dto.ErrorTipMap[dto.LogicError], Message: e.Error(), }) case dto.ErrorDto: e.Tip = dto.ErrorTipMap[e.Code] c.JSON(http.StatusInternalServerError, e) default: c.JSON(http.StatusInternalServerError, e) } c.Writer.WriteHeaderNow() c.Abort() })) return engine } func CustomRecoveryWithSlog(logger *slog.Logger, stack bool, recovery gin.RecoveryFunc) gin.HandlerFunc { 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 { logger.Error(c.Request.URL.Path, zap.Any("error", err), zap.String("request", string(httpRequest)), ) // If the connection is dead, we can't write a status to it. c.Error(err.(error)) // nolint: errcheck c.Abort() return } if stack { logger.Error("[Recovery from panic]", zap.Time("time", time.Now()), zap.Any("error", err), zap.String("request", string(httpRequest)), zap.String("stack", string(debug.Stack())), ) } else { logger.Error("[Recovery from panic]", zap.Time("time", time.Now()), zap.Any("error", err), zap.String("request", string(httpRequest)), ) } recovery(c, err) } }() c.Next() } }