123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- package middleware
- import (
- "bytes"
- "encoding/json"
- "fmt"
- "github.com/gin-gonic/gin"
- "github.com/go-nunu/nunu-layout-advanced/internal/model"
- "github.com/go-nunu/nunu-layout-advanced/internal/service"
- "github.com/go-nunu/nunu-layout-advanced/pkg/jwt"
- "io"
- "net/http"
- "strconv"
- )
- // OperationLogMiddleware 记录操作日志到数据库
- func OperationLogMiddleware(logService service.LogService) gin.HandlerFunc {
- return func(c *gin.Context) {
- var requestBody []byte
- if c.Request.Body != nil {
- requestBody, _ = io.ReadAll(c.Request.Body)
- c.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody))
- }
- blw := &bodyLogWriter{
- body: bytes.NewBufferString(""),
- ResponseWriter: c.Writer,
- }
- c.Writer = blw
- c.Next()
- go func() {
- ctxCopy := c.Copy()
- statusCode := ctxCopy.Writer.Status()
- var userID uint
- if claims, exists := ctxCopy.Get("claims"); exists {
- if customClaims, ok := claims.(*jwt.MyCustomClaims); ok {
- userID = customClaims.UserId
- }
- }
- // 如果JWT和Query中都没有,尝试从请求体中获取
- if userID == 0 && len(requestBody) > 0 {
- var bodyData map[string]interface{}
- if err := json.Unmarshal(requestBody, &bodyData); err == nil {
- if uidVal, ok := bodyData["uid"]; ok {
- if uidFloat, ok := uidVal.(float64); ok {
- userID = uint(uidFloat)
- }
- }
- }
- }
- if userID == 0 {
- if uidStr := ctxCopy.Query("uid"); uidStr != "" {
- if uid, err := strconv.ParseUint(uidStr, 10, 64); err == nil {
- userID = uint(uid)
- }
- }
- }
- if userID == 0 && (ctxCopy.Request.URL.Path == "/api/v1/login" || ctxCopy.Request.URL.Path == "/api/v1/user/login") && statusCode == http.StatusOK {
- var response struct {
- Data struct {
- ID uint `json:"id"`
- } `json:"data"`
- }
- if err := json.Unmarshal(blw.body.Bytes(), &response); err == nil {
- userID = response.Data.ID
- }
- }
- var traceID string
- if id, ok := ctxCopy.Get(TraceIDKey); ok {
- traceID, _ = id.(string)
- }
- var requestBodyForLog interface{}
- if len(requestBody) > 0 {
- if err := json.Unmarshal(requestBody, &requestBodyForLog); err != nil {
- // 如果解析失败, 则按原始字符串存储
- requestBodyForLog = string(requestBody)
- }
- }
- var responseBodyForLog interface{}
- responseBodyBytes := blw.body.Bytes()
- if len(responseBodyBytes) > 0 {
- if err := json.Unmarshal(responseBodyBytes, &responseBodyForLog); err != nil {
- // 如果解析失败, 则按原始字符串存储
- responseBodyForLog = blw.body.String()
- }
- }
- // 只记录请求体到 ExtraData
- extraData, _ := json.Marshal(requestBodyForLog)
- logEntry := &model.Log{
- TraceId: traceID,
- Uid: int64(userID),
- RequestIp: ctxCopy.ClientIP(),
- Api: ctxCopy.Request.RequestURI,
- Message: fmt.Sprintf("[%s] %s - %d", ctxCopy.Request.Method, ctxCopy.Request.URL.Path, statusCode),
- ExtraData: extraData,
- UserAgent: ctxCopy.Request.UserAgent(),
- StatusCode: statusCode,
- }
- _ = logService.AddLog(ctxCopy, logEntry)
- }()
- }
- }
|