如何在杜松子酒中记录响应体

时间:2016-07-21 10:10:58

标签: go go-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
        }
    }
}

我的问题是,如何从中间件中获取Context的响应主体?

2 个答案:

答案 0 :(得分:15)

您需要拦截响应的写入并将其存储在某处。然后你可以记录它。要做到这一点,你需要实现自己的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)

请注意,这个窗台不适用于静态文件,因为杜松子酒似乎没有使用c.Writer。但在大多数情况下,无论如何,这都是你想要的。

如果要拦截所有文件,则需要使用稍微复杂的方法。您需要实现一个包装器http.Handler而不是Middleware,它将包装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}

答案 1 :(得分:0)

仅供参考

注意:如果使用WriteString()编写响应正文,请实施c.String()

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())