从 golang net/http 库记录和解码响应体

use*_*731 3 go

我正在用 Go 编写一个 webhook 来解​​析 JSON 有效负载。我正在尝试记录原始有效负载,然后立即对其进行解码,但是当我尝试时它失败了。如果我分别执行这些操作,它们都可以独立正常工作。

有人可以解释为什么我不能使用ioutil.ReadAlljson.NewDecoder在一起?

func webhook(w http.ResponseWriter, r *http.Request) {
    body, _ := ioutil.ReadAll(r.Body)
    log.Printf("incoming message - %s", body)

    var p payload
    decoder := json.NewDecoder(r.Body)
    err := decoder.Decode(&p)
    if err != nil {
        // Returns EOF
        log.Printf("invalid payload - %s", err)
    }

    defer r.Body.Close()
}
Run Code Online (Sandbox Code Playgroud)

mko*_*iva 5

有人可以解释为什么我不能使用ioutil.ReadAlljson.NewDecoder 在一起?

请求正文是io.ReadCloser直接从网络连接读取或多或少字节的 。Body 的内容默认不存储在内存中。这就是为什么在您第一次阅读 Body 之后,下次尝试阅读它时,您会得到 EOF。

因此,如果您需要多次处理请求正文,您必须自己将内容存储到内存中,这就是您已经在做的事情:

body, _ := ioutil.ReadAll(r.Body)
Run Code Online (Sandbox Code Playgroud)

然后,您可以body根据需要多次重复使用,并且由于您可以使用 Body 内容作为[]byte值,因此您可以使用json.Unmarshal代替json.NewDecoder(...).Decode.


这与您的问题无关,但请不要忽略从 返回的错误ioutil.ReadAll

您也可以删除该defer r.Body.Close()行,因为您不必在服务器处理程序中关闭请求正文。(强调我的

对于服务器请求,请求正文始终为非零,但在没有正文时会立即返回 EOF。服务器将关闭请求正文。ServeHTTP 处理程序不需要。