66 lines
1.4 KiB
Go
66 lines
1.4 KiB
Go
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()
|
|
}
|