日志中request body 为空
logger 中间件中,打印出来的Request Body 一直是为空,其实是因为因为在控制器中对request body已经读取了一次,在中间件中再读取,就读取不到了。现在网上比较主流一点的解决方式是将request body处理一下,代码如下:
package middlewares
import (
"bytes"
"io/ioutil"
"time"
"github.com/gin-gonic/gin"
"github.com/spf13/cast"
"go.uber.org/zap"
"gohub/passport/pkg/helpers"
"gohub/passport/pkg/logger"
)
type responseBodyWriter struct {
gin.ResponseWriter
body *bytes.Buffer
}
// Write 重写gin.ResponseWriter Write方法
func (r responseBodyWriter) Write(b []byte) (int, error) {
r.body.Write(b)
return r.ResponseWriter.Write(b)
}
func Logger() gin.HandlerFunc {
return func(c *gin.Context) {
// 获取response 内容
w := &responseBodyWriter{body: &bytes.Buffer{}, ResponseWriter: c.Writer}
c.Writer = w
// 获取request body
reqeustBody, _ := c.GetRawData()
// 解决不可重复读body的问题
c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(reqeustBody))
// 设置开始时间
start := time.Now()
c.Next()
// 开始记录日志逻辑
cost := time.Since(start)
responseStatus := c.Writer.Status()
logFields := []zap.Field{
zap.Int("status", c.Writer.Status()),
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)),
}
if c.Request.Method == "POST" || c.Request.Method == "PUT" || c.Request.Method == "DELETE" {
// 请求的内容
logFields = append(logFields, zap.String("Request Body", string(reqeustBody)))
// 响应的内容
logFields = append(logFields, zap.String("Response Body", w.body.String()))
}
if responseStatus > 400 && responseStatus <= 499 {
// 除了 StatusBadRequest 以外,warning 提示一下,常见的有 403 404,开发时都要注意
logger.Warn("HTTP Warning "+cast.ToString(responseStatus), logFields...)
} else if responseStatus >= 500 && responseStatus <= 599 {
// 除了内部错误,记录 error
logger.Error("HTTP Error "+cast.ToString(responseStatus), logFields...)
} else {
logger.Debug("HTTP Access Log", logFields...)
}
}
}
欢迎其他大佬有更优雅的处理方式
关于 LearnKu
推荐文章: