【问题标题】:How to get data from http.ResponseWriter for logging如何从 http.ResponseWriter 获取数据以进行日志记录
【发布时间】:2017-10-03 18:03:58
【问题描述】:

我不知道这个问题是否有意义,但我想知道是否有任何方法可以获取写入http.ResponseWriter 的数据。我需要它来记录日志。

我在 Go 中编写了一个 API。

func api1(w http.ResponseWriter, req *http.Request) {       
    var requestData MyStruct
    err := json.NewDecoder(req.Body).Decode(&requestData)
    if err != nil {
        writeError(w, "JSON request is not in correct format")
        return
    }
    log.Println(" Request Data :", req.Body) // I am logging req
    result, err := compute()                 // getting result from a function

    if err != nil {
        errRes := ErrorResponse{"ERROR", err}
        response, er = json.Marshal(errRes) // getting error response
    } else {
        response, er = json.Marshal(result)
    }
    if er != nil {
        http.Error(w, er.Error(), 500) // writing error
        return
    }
    io.WriteString(w, string(response)) // writing response
}

目的是创建包含请求和响应数据的单个日志。响应可以是错误响应或已处理响应。

我在想如果我能得到写在 http.ResponseWriter 上的数据,我就可以创建一个有意义的日志。

这可能吗?如果没有,请建议我该如何实现。

【问题讨论】:

  • 传递给处理程序的http.ResponseWriter 不支持这一点,但很容易将其包装以支持您的需求。例如,查看这个可能的重复项(它详细说明了包含 RequestResponseWriter):Golang read request body
  • icza's 应该是公认的答案。 MultiWriter 生成一个 Writer 而不是 ResponseWriter .. 你需要添加它以使其在处理程序中可互换

标签: go


【解决方案1】:

添加到接受的答案。

我喜欢使用io.MultiWriter,但它只在这种情况下写入响应正文。

如果您想要标题,请使用 .Headers().Write 函数,如下所示...

func (w http.ResponseWriter, req *http.Request) {
    var log bytes.Buffer
    rsp := io.MultiWriter(w, &log)
    // from this point on use rsp instead of w, ie

    // get the response headers
    w.Header().Write(&log)

    err := json.NewDecoder(req.Body).Decode(&requestData)
    if err != nil {
        writeError(rsp, "JSON request is not in correct format")
        return
    }
    ...
}

【讨论】:

    【解决方案2】:

    您可以使用io.MultiWriter - 它创建一个写入器,将其写入复制到所有提供的写入器。所以要记录响应

    func api1(w http.ResponseWriter, req *http.Request) {
        var log bytes.Buffer
        rsp := io.MultiWriter(w, &log)
        // from this point on use rsp instead of w, ie
        err := json.NewDecoder(req.Body).Decode(&requestData)
        if err != nil {
            writeError(rsp, "JSON request is not in correct format")
            return
        }
        ...
    }
    

    现在您在wlog 中都有写入rsp 的信息的副本,您可以将log 缓冲区的内容保存到光盘上,以便在控制台等上显示。

    您可以使用io.TeeReader 创建一个读取器,将它从给定读取器读取的内容写入给定的写入器 - 这将允许您将req.Body 的副本保存到日志中,即

    func api1(w http.ResponseWriter, req *http.Request) {
        var log bytes.Buffer
        tee := io.TeeReader(req.Body, &log)
        err := json.NewDecoder(tee).Decode(&requestData)
        ...
    }
    

    现在,由于 json 解码器从 tee 中读取,req.Body 的内容也被复制到 log 缓冲区中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-06
      • 2012-03-02
      • 1970-01-01
      • 2015-03-08
      • 1970-01-01
      • 1970-01-01
      • 2022-08-17
      相关资源
      最近更新 更多