operation.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. package middleware
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "io"
  6. "net/http"
  7. "net/url"
  8. "server/dao/system"
  9. "strconv"
  10. "strings"
  11. "sync"
  12. "time"
  13. "server/utils"
  14. "github.com/gin-gonic/gin"
  15. "go.uber.org/zap"
  16. "server/global"
  17. "server/service"
  18. )
  19. var operationRecordService = service.ServiceGroupApp.SystemServiceGroup.OperationRecordService
  20. var respPool sync.Pool
  21. var bufferSize = 1024
  22. func init() {
  23. respPool.New = func() interface{} {
  24. return make([]byte, bufferSize)
  25. }
  26. }
  27. func OperationRecord() gin.HandlerFunc {
  28. return func(c *gin.Context) {
  29. var body []byte
  30. var userId int
  31. if c.Request.Method != http.MethodGet {
  32. var err error
  33. body, err = io.ReadAll(c.Request.Body)
  34. if err != nil {
  35. global.GVA_LOG.Error("read body from request error:", zap.Error(err))
  36. } else {
  37. c.Request.Body = io.NopCloser(bytes.NewBuffer(body))
  38. }
  39. } else {
  40. query := c.Request.URL.RawQuery
  41. query, _ = url.QueryUnescape(query)
  42. split := strings.Split(query, "&")
  43. m := make(map[string]string)
  44. for _, v := range split {
  45. kv := strings.Split(v, "=")
  46. if len(kv) == 2 {
  47. m[kv[0]] = kv[1]
  48. }
  49. }
  50. body, _ = json.Marshal(&m)
  51. }
  52. claims, _ := utils.GetClaims(c)
  53. if claims != nil && claims.BaseClaims.ID != 0 {
  54. userId = int(claims.BaseClaims.ID)
  55. } else {
  56. id, err := strconv.Atoi(c.Request.Header.Get("x-user-id"))
  57. if err != nil {
  58. userId = 0
  59. }
  60. userId = id
  61. }
  62. record := system.SysOperationRecord{
  63. Ip: c.ClientIP(),
  64. Method: c.Request.Method,
  65. Path: c.Request.URL.Path,
  66. Agent: c.Request.UserAgent(),
  67. Body: "",
  68. UserID: userId,
  69. }
  70. // 上传文件时候 中间件日志进行裁断操作
  71. if strings.Contains(c.GetHeader("Content-Type"), "multipart/form-data") {
  72. record.Body = "[文件]"
  73. } else {
  74. if len(body) > bufferSize {
  75. record.Body = "[超出记录长度]"
  76. } else {
  77. record.Body = string(body)
  78. }
  79. }
  80. writer := responseBodyWriter{
  81. ResponseWriter: c.Writer,
  82. body: &bytes.Buffer{},
  83. }
  84. c.Writer = writer
  85. now := time.Now()
  86. c.Next()
  87. latency := time.Since(now)
  88. record.ErrorMessage = c.Errors.ByType(gin.ErrorTypePrivate).String()
  89. record.Status = c.Writer.Status()
  90. record.Latency = latency
  91. record.Resp = writer.body.String()
  92. if strings.Contains(c.Writer.Header().Get("Pragma"), "public") ||
  93. strings.Contains(c.Writer.Header().Get("Expires"), "0") ||
  94. strings.Contains(c.Writer.Header().Get("Cache-Control"), "must-revalidate, post-check=0, pre-check=0") ||
  95. strings.Contains(c.Writer.Header().Get("Content-Type"), "application/force-download") ||
  96. strings.Contains(c.Writer.Header().Get("Content-Type"), "application/octet-stream") ||
  97. strings.Contains(c.Writer.Header().Get("Content-Type"), "application/vnd.ms-excel") ||
  98. strings.Contains(c.Writer.Header().Get("Content-Type"), "application/download") ||
  99. strings.Contains(c.Writer.Header().Get("Content-Disposition"), "attachment") ||
  100. strings.Contains(c.Writer.Header().Get("Content-Transfer-Encoding"), "binary") {
  101. if len(record.Resp) > bufferSize {
  102. // 截断
  103. record.Body = "超出记录长度"
  104. }
  105. }
  106. if err := operationRecordService.CreateSysOperationRecord(record); err != nil {
  107. global.GVA_LOG.Error("create operation record error:", zap.Error(err))
  108. }
  109. }
  110. }
  111. type responseBodyWriter struct {
  112. gin.ResponseWriter
  113. body *bytes.Buffer
  114. }
  115. func (r responseBodyWriter) Write(b []byte) (int, error) {
  116. r.body.Write(b)
  117. return r.ResponseWriter.Write(b)
  118. }