🎨 优化项目结构 && 完善ai配置

This commit is contained in:
2026-03-03 15:39:23 +08:00
parent 557c865948
commit 2714e63d2a
585 changed files with 62223 additions and 100018 deletions

View File

@@ -6,13 +6,15 @@ import (
"io"
"net/http"
"net/url"
"strconv"
"strings"
"sync"
"time"
"git.echol.cn/loser/ai_proxy/server/utils"
"git.echol.cn/loser/ai_proxy/server/global"
"git.echol.cn/loser/ai_proxy/server/model/system"
"git.echol.cn/loser/ai_proxy/server/utils"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
@@ -26,12 +28,10 @@ func init() {
}
}
// Operation 操作日志记录中间件
func Operation() gin.HandlerFunc {
func OperationRecord() gin.HandlerFunc {
return func(c *gin.Context) {
var body []byte
var userId int
if c.Request.Method != http.MethodGet {
var err error
body, err = io.ReadAll(c.Request.Body)
@@ -40,9 +40,48 @@ func Operation() gin.HandlerFunc {
} else {
c.Request.Body = io.NopCloser(bytes.NewBuffer(body))
}
} else {
query := c.Request.URL.RawQuery
query, _ = url.QueryUnescape(query)
split := strings.Split(query, "&")
m := make(map[string]string)
for _, v := range split {
kv := strings.Split(v, "=")
if len(kv) == 2 {
m[kv[0]] = kv[1]
}
}
body, _ = json.Marshal(&m)
}
claims, _ := utils.GetClaims(c)
if claims != nil && claims.BaseClaims.ID != 0 {
userId = int(claims.BaseClaims.ID)
} else {
id, err := strconv.Atoi(c.Request.Header.Get("x-user-id"))
if err != nil {
userId = 0
}
userId = id
}
record := system.SysOperationRecord{
Ip: c.ClientIP(),
Method: c.Request.Method,
Path: c.Request.URL.Path,
Agent: c.Request.UserAgent(),
Body: "",
UserID: userId,
}
userId = int(utils.GetUserID(c))
// 上传文件时候 中间件日志进行裁断操作
if strings.Contains(c.GetHeader("Content-Type"), "multipart/form-data") {
record.Body = "[文件]"
} else {
if len(body) > bufferSize {
record.Body = "[超出记录长度]"
} else {
record.Body = string(body)
}
}
writer := responseBodyWriter{
ResponseWriter: c.Writer,
@@ -54,66 +93,37 @@ func Operation() gin.HandlerFunc {
c.Next()
latency := time.Since(now)
record.ErrorMessage = c.Errors.ByType(gin.ErrorTypePrivate).String()
record.Status = c.Writer.Status()
record.Latency = latency
record.Resp = writer.body.String()
// 只记录需要的路径
if NeedRecordPath(c.Request.URL.Path) && c.Request.Method != http.MethodGet {
record := system.SysOperationRecord{
Ip: c.ClientIP(),
Method: c.Request.Method,
Path: c.Request.URL.Path,
Agent: c.Request.UserAgent(),
Body: string(body),
UserID: userId,
Status: c.Writer.Status(),
Latency: latency,
Resp: writer.body.String(),
if strings.Contains(c.Writer.Header().Get("Pragma"), "public") ||
strings.Contains(c.Writer.Header().Get("Expires"), "0") ||
strings.Contains(c.Writer.Header().Get("Cache-Control"), "must-revalidate, post-check=0, pre-check=0") ||
strings.Contains(c.Writer.Header().Get("Content-Type"), "application/force-download") ||
strings.Contains(c.Writer.Header().Get("Content-Type"), "application/octet-stream") ||
strings.Contains(c.Writer.Header().Get("Content-Type"), "application/vnd.ms-excel") ||
strings.Contains(c.Writer.Header().Get("Content-Type"), "application/download") ||
strings.Contains(c.Writer.Header().Get("Content-Disposition"), "attachment") ||
strings.Contains(c.Writer.Header().Get("Content-Transfer-Encoding"), "binary") {
if len(record.Resp) > bufferSize {
// 截断
record.Body = "超出记录长度"
}
values, _ := url.ParseQuery(c.Request.URL.RawQuery)
record.Query = values.Encode()
// 异步记录操作日志
go func() {
if err := operationRecordService.CreateSysOperationRecord(record); err != nil {
global.GVA_LOG.Error("create operation record error:", zap.Error(err))
}
}()
}
if err := global.GVA_DB.Create(&record).Error; err != nil {
global.GVA_LOG.Error("create operation record error:", zap.Error(err))
}
}
}
// FilteredPaths 需要过滤的路径
var FilteredPaths = []string{
"/health",
"/swagger",
"/api/captcha",
"/api/base/login",
type responseBodyWriter struct {
gin.ResponseWriter
body *bytes.Buffer
}
// ShouldRecord 判断是否应该记录该路径
func ShouldRecord(path string) bool {
for _, filtered := range FilteredPaths {
if strings.HasPrefix(path, filtered) {
return false
}
}
return true
}
// MaskSensitiveData 脱敏敏感数据
func MaskSensitiveData(data string) string {
var result map[string]interface{}
if err := json.Unmarshal([]byte(data), &result); err != nil {
return data
}
sensitiveFields := []string{"password", "token", "secret", "key"}
for _, field := range sensitiveFields {
if _, ok := result[field]; ok {
result[field] = "******"
}
}
masked, _ := json.Marshal(result)
return string(masked)
func (r responseBodyWriter) Write(b []byte) (int, error) {
r.body.Write(b)
return r.ResponseWriter.Write(b)
}