feat(sync): full code sync from release

This commit is contained in:
yangjianbo
2026-02-28 15:01:20 +08:00
parent bfc7b339f7
commit bb664d9bbf
338 changed files with 54513 additions and 2011 deletions

View File

@@ -3,7 +3,9 @@ package logredact
import (
"encoding/json"
"regexp"
"sort"
"strings"
"sync"
)
// maxRedactDepth 限制递归深度以防止栈溢出
@@ -31,9 +33,18 @@ var defaultSensitiveKeyList = []string{
"password",
}
type textRedactPatterns struct {
reJSONLike *regexp.Regexp
reQueryLike *regexp.Regexp
rePlain *regexp.Regexp
}
var (
reGOCSPX = regexp.MustCompile(`GOCSPX-[0-9A-Za-z_-]{24,}`)
reAIza = regexp.MustCompile(`AIza[0-9A-Za-z_-]{35}`)
defaultTextRedactPatterns = compileTextRedactPatterns(nil)
extraTextPatternCache sync.Map // map[string]*textRedactPatterns
)
func RedactMap(input map[string]any, extraKeys ...string) map[string]any {
@@ -83,23 +94,71 @@ func RedactText(input string, extraKeys ...string) string {
return RedactJSON(raw, extraKeys...)
}
keyAlt := buildKeyAlternation(extraKeys)
// JSON-like: "access_token":"..."
reJSONLike := regexp.MustCompile(`(?i)("(?:` + keyAlt + `)"\s*:\s*")([^"]*)(")`)
// Query-like: access_token=...
reQueryLike := regexp.MustCompile(`(?i)\b((?:` + keyAlt + `))=([^&\s]+)`)
// Plain: access_token: ... / access_token = ...
rePlain := regexp.MustCompile(`(?i)\b((?:` + keyAlt + `))\b(\s*[:=]\s*)([^,\s]+)`)
patterns := getTextRedactPatterns(extraKeys)
out := input
out = reGOCSPX.ReplaceAllString(out, "GOCSPX-***")
out = reAIza.ReplaceAllString(out, "AIza***")
out = reJSONLike.ReplaceAllString(out, `$1***$3`)
out = reQueryLike.ReplaceAllString(out, `$1=***`)
out = rePlain.ReplaceAllString(out, `$1$2***`)
out = patterns.reJSONLike.ReplaceAllString(out, `$1***$3`)
out = patterns.reQueryLike.ReplaceAllString(out, `$1=***`)
out = patterns.rePlain.ReplaceAllString(out, `$1$2***`)
return out
}
func compileTextRedactPatterns(extraKeys []string) *textRedactPatterns {
keyAlt := buildKeyAlternation(extraKeys)
return &textRedactPatterns{
// JSON-like: "access_token":"..."
reJSONLike: regexp.MustCompile(`(?i)("(?:` + keyAlt + `)"\s*:\s*")([^"]*)(")`),
// Query-like: access_token=...
reQueryLike: regexp.MustCompile(`(?i)\b((?:` + keyAlt + `))=([^&\s]+)`),
// Plain: access_token: ... / access_token = ...
rePlain: regexp.MustCompile(`(?i)\b((?:` + keyAlt + `))\b(\s*[:=]\s*)([^,\s]+)`),
}
}
func getTextRedactPatterns(extraKeys []string) *textRedactPatterns {
normalizedExtraKeys := normalizeAndSortExtraKeys(extraKeys)
if len(normalizedExtraKeys) == 0 {
return defaultTextRedactPatterns
}
cacheKey := strings.Join(normalizedExtraKeys, ",")
if cached, ok := extraTextPatternCache.Load(cacheKey); ok {
if patterns, ok := cached.(*textRedactPatterns); ok {
return patterns
}
}
compiled := compileTextRedactPatterns(normalizedExtraKeys)
actual, _ := extraTextPatternCache.LoadOrStore(cacheKey, compiled)
if patterns, ok := actual.(*textRedactPatterns); ok {
return patterns
}
return compiled
}
func normalizeAndSortExtraKeys(extraKeys []string) []string {
if len(extraKeys) == 0 {
return nil
}
seen := make(map[string]struct{}, len(extraKeys))
keys := make([]string, 0, len(extraKeys))
for _, key := range extraKeys {
normalized := normalizeKey(key)
if normalized == "" {
continue
}
if _, ok := seen[normalized]; ok {
continue
}
seen[normalized] = struct{}{}
keys = append(keys, normalized)
}
sort.Strings(keys)
return keys
}
func buildKeyAlternation(extraKeys []string) string {
seen := make(map[string]struct{}, len(defaultSensitiveKeyList)+len(extraKeys))
keys := make([]string, 0, len(defaultSensitiveKeyList)+len(extraKeys))