kra-new/app/system/internal/server/middleware/capture.go

75 lines
1.5 KiB
Go

package middleware
import (
"bytes"
"encoding/json"
"strings"
"github.com/gin-gonic/gin"
)
// The global access logger is the single request/response capture point.
// OperationAudit consumes these values after the handler returns, avoiding a
// second body read/writer wrapper.
const (
ctxReqBodyKey = "kra_req_body"
ctxRespBufferKey = "kra_resp_buffer"
)
type captureWriter struct {
gin.ResponseWriter
body bytes.Buffer
maxBytes int
}
func (w *captureWriter) Write(data []byte) (int, error) {
limit := w.maxBytes
if limit <= 0 {
limit = 1024
}
if w.body.Len() < limit {
remaining := limit - w.body.Len()
if len(data) > remaining {
_, _ = w.body.Write(data[:remaining])
} else {
_, _ = w.body.Write(data)
}
}
return w.ResponseWriter.Write(data)
}
func redactJSON(raw []byte, contentType string, limit int) string {
if len(raw) == 0 {
return ""
}
if limit <= 0 {
limit = 1024
}
text := string(raw)
if !strings.Contains(strings.ToLower(contentType), "json") {
if len(text) > limit {
return "[超出记录长度]"
}
return text
}
var value any
if json.Unmarshal(raw, &value) != nil {
if len(text) > limit {
return "[超出记录长度]"
}
return text
}
maskOperationBody(value)
encoded, _ := json.Marshal(value)
if len(encoded) > limit {
return "[超出记录长度]"
}
return string(encoded)
}
func stringValue(value any) string { text, _ := value.(string); return text }
func isBootstrapPath(path string) bool {
return strings.HasSuffix(path, "/health") || strings.Contains(path, "/init/")
}