package middleware import ( "context" "net" "os" "runtime/debug" "strings" "github.com/go-kratos/kratos/v2/errors" "github.com/go-kratos/kratos/v2/log" "github.com/go-kratos/kratos/v2/middleware" ) // Recovery panic恢复中间件 func Recovery(logger log.Logger) middleware.Middleware { helper := log.NewHelper(logger) return func(handler middleware.Handler) middleware.Handler { return func(ctx context.Context, req interface{}) (reply interface{}, err error) { defer func() { if rerr := recover(); rerr != nil { // 检查是否为断开的连接 var brokenPipe bool if ne, ok := rerr.(*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 } } } stack := string(debug.Stack()) if brokenPipe { helper.Errorw( "msg", "[Recovery from panic]", "error", rerr, "broken_pipe", true, ) } else { helper.Errorw( "msg", "[Recovery from panic]", "error", rerr, "stack", stack, ) } err = errors.InternalServer("PANIC", "服务器内部错误") } }() return handler(ctx, req) } } }