operation.go 3.4 KB

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