package middleware import ( "bytes" "io" "strconv" "time" "kra/pkg/utils" "github.com/gin-gonic/gin" "go.uber.org/zap" ) // EmailSender 邮件发送接口 type EmailSender interface { ErrorToEmail(subject, body string) error } // UserFinder 用户查找接口 type UserFinder interface { FindUsernameByID(id int) (string, error) } // EmailConfig 邮件中间件配置 type EmailConfig struct { EmailSender EmailSender UserFinder UserFinder Logger *zap.Logger } // 全局邮件配置 var emailConfig *EmailConfig // SetEmailConfig 设置邮件配置 func SetEmailConfig(cfg *EmailConfig) { emailConfig = cfg } // ErrorToEmail 错误发送邮件中间件(与 kra 保持一致) func ErrorToEmail() gin.HandlerFunc { return func(c *gin.Context) { var username string // 获取用户信息 claims, _ := utils.GetClaims(c) if claims != nil && claims.Username != "" { username = claims.Username } else { id, _ := strconv.Atoi(c.Request.Header.Get("x-user-id")) if id > 0 && emailConfig != nil && emailConfig.UserFinder != nil { if name, err := emailConfig.UserFinder.FindUsernameByID(id); err == nil { username = name } else { username = "Unknown" } } else { username = "Unknown" } } // 读取请求体 body, _ := io.ReadAll(c.Request.Body) // 将原body塞回去 c.Request.Body = io.NopCloser(bytes.NewBuffer(body)) // 记录请求信息 record := struct { IP string Method string Path string Agent string Body string }{ IP: c.ClientIP(), Method: c.Request.Method, Path: c.Request.URL.Path, Agent: c.Request.UserAgent(), Body: string(body), } now := time.Now() c.Next() latency := time.Since(now) status := c.Writer.Status() errorMessage := c.Errors.ByType(gin.ErrorTypePrivate).String() // 构建邮件内容 str := "接收到的请求为" + record.Body + "\n" + "请求方式为" + record.Method + "\n" + "报错信息如下" + errorMessage + "\n" + "耗时" + latency.String() + "\n" // 如果状态码不是200,发送邮件 if status != 200 { subject := username + " " + record.IP + "调用了" + record.Path + "报错了" if emailConfig != nil && emailConfig.EmailSender != nil { if err := emailConfig.EmailSender.ErrorToEmail(subject, str); err != nil { if emailConfig.Logger != nil { emailConfig.Logger.Error("ErrorToEmail Failed, err:", zap.Error(err)) } } } } } }