package middleware import ( "net/http" "runtime/debug" "strings" "time" "git.iwork-ai.com/xdc/iqudo-top1/internal/auth" "git.iwork-ai.com/xdc/iqudo-top1/internal/response" "github.com/gin-gonic/gin" "github.com/google/uuid" "go.uber.org/zap" ) func RequestLogger(log *zap.Logger) gin.HandlerFunc { return func(c *gin.Context) { started := time.Now() requestID := c.GetHeader("X-Request-ID") if requestID == "" { requestID = uuid.NewString() } c.Set("request_id", requestID) c.Header("X-Request-ID", requestID) c.Next() fields := []zap.Field{ zap.String("request_id", requestID), zap.String("method", c.Request.Method), zap.String("path", c.Request.URL.Path), zap.Int("status", c.Writer.Status()), zap.Int("response_bytes", c.Writer.Size()), zap.Duration("duration", time.Since(started)), zap.String("client_ip", c.ClientIP()), } if principal, ok := auth.PrincipalFromContext(c); ok { fields = append(fields, zap.Uint64("tenant_id", principal.TenantID), zap.Uint64("user_id", principal.UserID)) } if len(c.Errors) > 0 { fields = append(fields, zap.String("errors", c.Errors.String())) } log.Info("http request", fields...) } } func Recovery(log *zap.Logger) gin.HandlerFunc { return func(c *gin.Context) { defer func() { if recovered := recover(); recovered != nil { log.Error("panic recovered", zap.Any("panic", recovered), zap.ByteString("stack", debug.Stack())) response.Error(c, http.StatusInternalServerError, "INTERNAL_ERROR", "服务暂时不可用") } }() c.Next() } } func Authenticate(service *auth.Service) gin.HandlerFunc { return func(c *gin.Context) { header := c.GetHeader("Authorization") parts := strings.SplitN(header, " ", 2) if len(parts) != 2 || !strings.EqualFold(parts[0], "Bearer") { response.Error(c, http.StatusUnauthorized, "UNAUTHORIZED", "请先登录") return } principal, err := service.ParseAccessToken(parts[1]) if err != nil { response.Error(c, http.StatusUnauthorized, "INVALID_TOKEN", "登录状态已失效") return } auth.SetPrincipal(c, principal) c.Next() } }