package middleware import ( "crypto/rand" "encoding/hex" "net/url" "strings" "time" "github.com/gin-gonic/gin" ) const RequestIDHeader = "X-Request-ID" // RequestID 返回当前请求 ID。 func RequestID(c *gin.Context) string { value, _ := c.Get("requestId") if id, ok := value.(string); ok { return id } return "" } // RequestIDMiddleware 生成或透传 X-Request-ID。 func RequestIDMiddleware() gin.HandlerFunc { return func(c *gin.Context) { id := c.GetHeader(RequestIDHeader) if id == "" { id = randomRequestID() } c.Set("requestId", id) c.Header(RequestIDHeader, id) c.Next() } } func randomRequestID() string { b := make([]byte, 16) if _, err := rand.Read(b); err != nil { return "req-" + hex.EncodeToString([]byte(time.Now().Format(time.RFC3339Nano))) } return hex.EncodeToString(b) } // RedactSensitiveQuery 脱敏 URL query 中的 token/password/secret。 func RedactSensitiveQuery(rawQuery string) string { if rawQuery == "" { return "" } values, err := url.ParseQuery(rawQuery) if err != nil { return "[invalid-query]" } keys := make([]string, 0, len(values)) for key := range values { keys = append(keys, key) } for _, key := range keys { lower := strings.ToLower(key) if strings.Contains(lower, "token") || strings.Contains(lower, "password") || strings.Contains(lower, "secret") || strings.Contains(lower, "authorization") { values.Set(key, "[redacted]") } } return values.Encode() }