ifms_go/pkg/middleware/recover.go
2025-06-10 17:50:46 +08:00

60 lines
1.5 KiB
Go

package middleware
import (
"fmt"
"net/http/httputil"
"strings"
"time"
"ifms/pkg/errors"
"ifms/pkg/logging"
"ifms/pkg/util"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
type RecoveryConfig struct {
Skip int // default: 3
}
var DefaultRecoveryConfig = RecoveryConfig{
Skip: 3,
}
// Recovery from any panics and writes a 500 if there was one.
func Recovery() gin.HandlerFunc {
return RecoveryWithConfig(DefaultRecoveryConfig)
}
func RecoveryWithConfig(config RecoveryConfig) gin.HandlerFunc {
return func(c *gin.Context) {
defer func() {
if rv := recover(); rv != nil {
ctx := c.Request.Context()
ctx = logging.NewTag(ctx, logging.TagKeyRecovery)
var fields []zap.Field
fields = append(fields, zap.Strings("error", []string{fmt.Sprintf("%v", rv)}))
fields = append(fields, zap.StackSkip("stack", config.Skip))
if gin.IsDebugging() {
httpRequest, _ := httputil.DumpRequest(c.Request, false)
headers := strings.Split(string(httpRequest), "\r\n")
for idx, header := range headers {
current := strings.Split(header, ":")
if current[0] == "Authorization" {
headers[idx] = current[0] + ": *"
}
}
fields = append(fields, zap.Strings("headers", headers))
}
logging.Context(ctx).Error(fmt.Sprintf("[Recovery] %s panic recovered", time.Now().Format("2006/01/02 - 15:04:05")), fields...)
util.ResError(c, errors.InternalServerError("", "Internal server error, please try again later"))
}
}()
c.Next()
}
}