用于http.request的golang多个parseBody

时间:2018-07-19 14:34:45

标签: http go web web-development-server

嘿,我想解析一个http.resquest两次,如下所示。当我第一次解析Body时,body将关闭。我需要一些帮助/提示,​​最好的方法是处理此问题,我是否必须创建请求的副本,还是有更好的方法?

func myfunc(w http.ResponseWriter, req *http.Request) {
  err := parseBody(req, &type1){
  .....
  }

  err := parseBody(req, &type2){
  .....
  }
}

感谢帮助

2 个答案:

答案 0 :(得分:2)

的确,您只能阅读一次正文,这是可以的,因为可以多次解析正文,而不必阅读一次以上。让我们考虑一个简单的例子:

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
)

type RequestData1 struct {
    Code   string `json:"code"`
    Status string `json:"status"`
}

type RequestData2 struct {
    Status  string `json:"status"`
    Message string `json:"message"`
}

func main() {
    http.HandleFunc("/post", post)
    http.ListenAndServe(":8080", nil)
}

如果我们使用以下代码:

func post(w http.ResponseWriter, r *http.Request) {
    body1, err := ioutil.ReadAll(r.Body)
    if err != nil {
        panic(err)
    }
    rd1 := RequestData1{}
    err = json.Unmarshal(body1, &rd1)
    if err != nil {
        panic(err)
    }

    body2, err := ioutil.ReadAll(r.Body)
    if err != nil {
        panic(err)
    }
    rd2 := RequestData2{}
    err = json.Unmarshal(body2, &rd2)
    if err != nil {
        panic(err) // panic!!!
    }

    fmt.Printf("rd1: %+v \nrd2: %+v", rd1, rd2)
    w.WriteHeader(http.StatusOK)
    w.Write([]byte(`Look into console.`))
}

我们会感到恐慌:http: panic serving [::1]:54581: unexpected end of JSON input
但带有下一个代码:

func post(w http.ResponseWriter, r *http.Request) {
    body, err := ioutil.ReadAll(r.Body)
    if err != nil {
        panic(err)
    }

    rd1 := RequestData1{}
    err = json.Unmarshal(body, &rd1)
    if err != nil {
        panic(err)
    }

    rd2 := RequestData2{}
    err = json.Unmarshal(body, &rd2)
    if err != nil {
        panic(err)
    }

    fmt.Printf("rd1: %+v \nrd2: %+v", rd1, rd2)
    w.WriteHeader(http.StatusOK)
    w.Write([]byte(`Look into console.`))
}

所有作品!您可以通过发出请求进行测试:

curl -X POST 'http://localhost:8080/post' \
-H 'Content-Type: application/json' -d '{"code":"200", "status": "OK", "message": "200 OK"}'

结果将是:

rd1: {Code:200 Status:OK}
rd2: {Status:OK Message:200 OK}

答案 1 :(得分:0)

阅读request.Body时,就是从客户端(例如Web浏览器)读取流。客户端仅发送一次请求。如果要多次解析,请将整个内容读入缓冲区(例如[]byte),然后根据需要进行多次解析。请注意许多带有较大有效负载的并发请求可能会占用内存,因为您将至少在完全完成解析之前将完整的有效负载保存在内存中。