mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2024-12-12 07:29:11 +08:00
96 lines
2.1 KiB
Go
96 lines
2.1 KiB
Go
|
package middleware
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"io/ioutil"
|
||
|
"net/http"
|
||
|
"strings"
|
||
|
"time"
|
||
|
|
||
|
"github.com/1Panel-dev/1Panel/app/model"
|
||
|
"github.com/1Panel-dev/1Panel/app/service"
|
||
|
"github.com/1Panel-dev/1Panel/global"
|
||
|
"github.com/gin-gonic/gin"
|
||
|
)
|
||
|
|
||
|
func OperationRecord() gin.HandlerFunc {
|
||
|
return func(c *gin.Context) {
|
||
|
var body []byte
|
||
|
if c.Request.Method == http.MethodGet || strings.Contains(c.Request.URL.Path, "search") {
|
||
|
c.Next()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
var err error
|
||
|
body, err = ioutil.ReadAll(c.Request.Body)
|
||
|
if err != nil {
|
||
|
global.LOG.Errorf("read body from request failed, err: %v", err)
|
||
|
} else {
|
||
|
c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(body))
|
||
|
}
|
||
|
pathInfo := loadLogInfo(c.Request.URL.Path)
|
||
|
|
||
|
record := model.OperationLog{
|
||
|
Group: pathInfo.group,
|
||
|
Source: pathInfo.source,
|
||
|
Action: pathInfo.action,
|
||
|
IP: c.ClientIP(),
|
||
|
Method: c.Request.Method,
|
||
|
Path: c.Request.URL.Path,
|
||
|
UserAgent: c.Request.UserAgent(),
|
||
|
Body: string(body),
|
||
|
}
|
||
|
|
||
|
writer := responseBodyWriter{
|
||
|
ResponseWriter: c.Writer,
|
||
|
body: &bytes.Buffer{},
|
||
|
}
|
||
|
c.Writer = writer
|
||
|
now := time.Now()
|
||
|
|
||
|
c.Next()
|
||
|
|
||
|
latency := time.Since(now)
|
||
|
record.Latency = latency
|
||
|
record.Resp = writer.body.String()
|
||
|
|
||
|
if err := service.NewIOperationService().Create(record); err != nil {
|
||
|
global.LOG.Errorf("create operation record failed, err: %v", err)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type responseBodyWriter struct {
|
||
|
gin.ResponseWriter
|
||
|
body *bytes.Buffer
|
||
|
}
|
||
|
|
||
|
func (r responseBodyWriter) Write(b []byte) (int, error) {
|
||
|
r.body.Write(b)
|
||
|
return r.ResponseWriter.Write(b)
|
||
|
}
|
||
|
|
||
|
type pathInfo struct {
|
||
|
group string
|
||
|
source string
|
||
|
action string
|
||
|
}
|
||
|
|
||
|
func loadLogInfo(path string) pathInfo {
|
||
|
path = strings.ReplaceAll(path, "/api/v1", "")
|
||
|
if !strings.Contains(path, "/") {
|
||
|
return pathInfo{}
|
||
|
}
|
||
|
pathArrys := strings.Split(path, "/")
|
||
|
if len(pathArrys) < 2 {
|
||
|
return pathInfo{}
|
||
|
}
|
||
|
if len(pathArrys) == 2 {
|
||
|
return pathInfo{group: pathArrys[1]}
|
||
|
}
|
||
|
if len(pathArrys) == 3 {
|
||
|
return pathInfo{group: pathArrys[1], source: pathArrys[2]}
|
||
|
}
|
||
|
return pathInfo{group: pathArrys[1], source: pathArrys[2], action: pathArrys[3]}
|
||
|
}
|