如何在杜松子酒中记录响应体
How to log response body in gin
我需要在 gin 的中间件中记录响应主体,但我没有找到如何获取响应主体。有人可以帮忙吗?
我正在使用这样的中间件:
func Logger() gin.HandlerFunc {
return func(c *gin.Context) {
c.Next()
statusCode := c.Writer.Status()
if statusCode >= 400 {
//ok this is an request with error, let's make a record for it
//log body here
}
}
}
我的问题是,如何从中间件中的上下文获取响应体?
您需要拦截响应的写入并将其存储在某个地方。然后你可以记录它。为此,您需要实现自己的 Writer 拦截 Write() 调用。
例如如下:
type bodyLogWriter struct {
gin.ResponseWriter
body *bytes.Buffer
}
func (w bodyLogWriter) Write(b []byte) (int, error) {
w.body.Write(b)
return w.ResponseWriter.Write(b)
}
func ginBodyLogMiddleware(c *gin.Context) {
blw := &bodyLogWriter{body: bytes.NewBufferString(""), ResponseWriter: c.Writer}
c.Writer = blw
c.Next()
statusCode := c.Writer.Status()
if statusCode >= 400 {
//ok this is an request with error, let's make a record for it
// now print body (or log in your preferred way)
fmt.Println("Response body: " + blw.body.String())
}
}
然后像这样使用这个中间件:
router.Use(ginBodyLogMiddleware)
请注意,此门槛不适用于静态文件,因为 gin 似乎不对它们使用 c.Writer。但在大多数情况下,这就是你想要的。
如果要拦截所有文件,需要使用稍微复杂一点的方法。您需要实现一个包装器 http.Handler 而不是中间件,它将包装 gin.Engine 并将使用与上面所示相同的方法来拦截和记录写入 http.ResponseWriter 的任何内容。然后 运行 像这样的 gin 服务器:
ginRouter := gin.New()
// configure your middleware and routes as required
// Run http server as follows, where bodyLogHandler is your wrapper handler
http.ListenAndServe(bindAddress, &bodyLogHandler{wrappedHandler: ginRouter}
仅供参考
注意:如果使用 c.String()
编写响应正文,请实施 WriteString()
type bodyLogWriter struct {
gin.ResponseWriter
body *bytes.Buffer
}
func (w bodyLogWriter) Write(b []byte) (int, error) {
w.body.Write(b)
return w.ResponseWriter.Write(b)
}
func (w bodyLogWriter) WriteString(s string) (int, error) {
w.body.WriteString(s)
return w.ResponseWriter.WriteString(s)
}
func ginBodyLogMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
blw := &bodyLogWriter{body: bytes.NewBufferString(""), ResponseWriter: c.Writer}
c.Writer = blw
c.Next()
fmt.Println("Response body: " + blw.body.String())
}
}
...
// register
router := r.Group("/", ginBodyLogMiddleware())
我需要在 gin 的中间件中记录响应主体,但我没有找到如何获取响应主体。有人可以帮忙吗?
我正在使用这样的中间件:
func Logger() gin.HandlerFunc {
return func(c *gin.Context) {
c.Next()
statusCode := c.Writer.Status()
if statusCode >= 400 {
//ok this is an request with error, let's make a record for it
//log body here
}
}
}
我的问题是,如何从中间件中的上下文获取响应体?
您需要拦截响应的写入并将其存储在某个地方。然后你可以记录它。为此,您需要实现自己的 Writer 拦截 Write() 调用。
例如如下:
type bodyLogWriter struct {
gin.ResponseWriter
body *bytes.Buffer
}
func (w bodyLogWriter) Write(b []byte) (int, error) {
w.body.Write(b)
return w.ResponseWriter.Write(b)
}
func ginBodyLogMiddleware(c *gin.Context) {
blw := &bodyLogWriter{body: bytes.NewBufferString(""), ResponseWriter: c.Writer}
c.Writer = blw
c.Next()
statusCode := c.Writer.Status()
if statusCode >= 400 {
//ok this is an request with error, let's make a record for it
// now print body (or log in your preferred way)
fmt.Println("Response body: " + blw.body.String())
}
}
然后像这样使用这个中间件:
router.Use(ginBodyLogMiddleware)
请注意,此门槛不适用于静态文件,因为 gin 似乎不对它们使用 c.Writer。但在大多数情况下,这就是你想要的。
如果要拦截所有文件,需要使用稍微复杂一点的方法。您需要实现一个包装器 http.Handler 而不是中间件,它将包装 gin.Engine 并将使用与上面所示相同的方法来拦截和记录写入 http.ResponseWriter 的任何内容。然后 运行 像这样的 gin 服务器:
ginRouter := gin.New()
// configure your middleware and routes as required
// Run http server as follows, where bodyLogHandler is your wrapper handler
http.ListenAndServe(bindAddress, &bodyLogHandler{wrappedHandler: ginRouter}
仅供参考
注意:如果使用 c.String()
编写响应正文,请实施 WriteString()
type bodyLogWriter struct {
gin.ResponseWriter
body *bytes.Buffer
}
func (w bodyLogWriter) Write(b []byte) (int, error) {
w.body.Write(b)
return w.ResponseWriter.Write(b)
}
func (w bodyLogWriter) WriteString(s string) (int, error) {
w.body.WriteString(s)
return w.ResponseWriter.WriteString(s)
}
func ginBodyLogMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
blw := &bodyLogWriter{body: bytes.NewBufferString(""), ResponseWriter: c.Writer}
c.Writer = blw
c.Next()
fmt.Println("Response body: " + blw.body.String())
}
}
...
// register
router := r.Group("/", ginBodyLogMiddleware())