package middlewares import ( "bytes" "io" "time" "github.com/gin-gonic/gin" "github.com/spf13/cast" "go.uber.org/zap" "github.com/runningwater/gohub/pkg/helpers" "github.com/runningwater/gohub/pkg/logger" ) 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) } // Logger 记录请求日志 func Logger() gin.HandlerFunc { return func(c *gin.Context) { // 获取 response 内容 w := &responseBodyWriter{body: &bytes.Buffer{}, ResponseWriter: c.Writer} c.Writer = w // 获取请求数据 var requestBody []byte if c.Request.Body != nil { // 读取 c.Request.Body 内容 requestBody, _ = io.ReadAll(c.Request.Body) // 重新赋值 c.Request.Body ,以供后续的其他方法读取 c.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody)) } // 设置开始时间 start := time.Now() c.Next() // 开始记录日志的逻辑 cost := time.Since(start) responseStatus := c.Writer.Status() logFields := []zap.Field{ zap.Int("status", responseStatus), zap.String("request", c.Request.Method+c.Request.URL.String()), zap.String("query", c.Request.URL.RawQuery), zap.String("ip", c.ClientIP()), zap.String("user-agent", c.Request.UserAgent()), zap.String("errors", c.Errors.ByType(gin.ErrorTypePrivate).String()), zap.String("time", helpers.MicrosecondsStr(cost)), } // Body 内容 if c.Request.Method == "POST" || c.Request.Method == "PUT" || c.Request.Method == "DELETE" { logFields = append(logFields, zap.String("RequestBody", string(requestBody))) logFields = append(logFields, zap.String("ResponseBody", w.body.String())) } if responseStatus > 400 && responseStatus < 500 { // 403 404 等客户端错误,使用 Warn 级别 logger.Warn("HTTP Warning "+cast.ToString(responseStatus), logFields...) } else if responseStatus >= 500 && responseStatus < 600 { logger.Error("HTTP Error "+cast.ToString(responseStatus), logFields...) } else { logger.Debug("HTTP Access Log", logFields...) } } }