mengstack-api/internal/app/middleware/requestid.go
MengStack Dev 9148d2f6da
Some checks failed
CI / Build & Test (push) Failing after 33s
feat: Swagger 全量注解 + M8 质量加固
- 37 个端点全部添加 godoc Swagger 注解(RBAC 11 / Org 5 / Audit 1 / Settings 7 / Notification 7)
- 重新生成 docs/(swagger.json/yaml/docs.go)
- M8 质量横切:IP 限流、安全头、Body 限制、结构化日志增强、优雅关闭
- 新增 Dockerfile 多阶段构建 + .dockerignore
- 新增 testutil 测试工具包
- 修复 testutil.go 编译错误
2026-10-03 01:57:39 +08:00

73 lines
1.6 KiB
Go

package middleware
import (
"time"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"go.uber.org/zap"
)
func RequestID() gin.HandlerFunc {
return func(c *gin.Context) {
traceID := c.GetHeader("X-Request-ID")
if traceID == "" {
traceID = uuid.New().String()
}
c.Set("trace_id", traceID)
c.Header("X-Request-ID", traceID)
c.Next()
}
}
func RequestLogger(log *zap.Logger) gin.HandlerFunc {
return func(c *gin.Context) {
start := time.Now()
path := c.Request.URL.Path
query := c.Request.URL.RawQuery
c.Next()
latency := time.Since(start)
status := c.Writer.Status()
fields := []zap.Field{
zap.Int("status", status),
zap.String("method", c.Request.Method),
zap.String("path", path),
zap.String("query", query),
zap.String("ip", c.ClientIP()),
zap.String("user-agent", c.Request.UserAgent()),
zap.Duration("latency", latency),
zap.String("trace_id", c.GetString("trace_id")),
}
if c.Writer.Status() >= 500 {
log.Error("request completed with server error", fields...)
} else if c.Writer.Status() >= 400 {
log.Warn("request completed with client error", fields...)
} else {
log.Info("request", fields...)
}
}
}
func Recovery(log *zap.Logger) gin.HandlerFunc {
return func(c *gin.Context) {
defer func() {
if r := recover(); r != nil {
log.Error("panic recovered",
zap.Any("error", r),
zap.String("path", c.Request.URL.Path),
zap.String("trace_id", c.GetString("trace_id")),
)
c.AbortWithStatusJSON(500, gin.H{
"error": "INTERNAL_ERROR",
"message": "internal server error",
})
}
}()
c.Next()
}
}