简体   繁体   English

我如何才能在一个处理程序中使用更多的 http.Request?

[英]How i can use http.Request more then in one handler?

I have a basic middlewear it's a Logger function, and when I do body, err := ioutil.ReadAll(r.Body) in each of the next functions http.Request will be empty.我有一个基本的body, err := ioutil.ReadAll(r.Body)它是一个 Logger 函数,当我执行body, err := ioutil.ReadAll(r.Body)下一个函数 http.Request 中的每个函数body, err := ioutil.ReadAll(r.Body)将为空。 But i want that the body contains information.但我希望身体包含信息。 What can I do?我能做什么?

Start:开始:

r.HandleFunc("/login", server.Loger(server.GetTokenHandler()).ServeHTTP).Methods("POST")

So it's middlewear:所以是中装:

func (server Server) Loger(h http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        body, _ := ioutil.ReadAll(r.Body)
        server.Log.Info(r.URL, " Methods: ", r.Method, string(body))
        h.ServeHTTP(w, r) //Calls handler h
    })
}

And now r.Body will be empty:现在 r.Body 将是空的:

func (server Server) GetTokenHandler()  http.Handler{
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        body, err := ioutil.ReadAll(r.Body)
        if err != nil{
            http.Error(w, "", 400)
            server.Log.Error(err)
            return
        }
        fmt.Print(string(body))
    })
}

The r.Body can be only read once. r.Body只能读取一次。 There is no way around it.没有其他办法了。

If multiple middleware need to access the data, you need to save it a byte slice and pass it to subsequent middlewares.如果多个中间件需要访问数据,则需要保存一个字节片,传递给后续的中间件。

If the handler had a context, you could have passed the body data as a value in the context.如果处理程序有上下文,您可以将正文数据作为上下文中的值传递。

Another solution, which is a hack, is to store the data in a header field of the ReponseWriter.另一种解决方案是将数据存储在 ReponseWriter 的标头字段中,这是一种 hack。 You should not forget to remove it when returning so that it's not sent out.返回时不要忘记将其删除,以免发送出去。 Subsequent middleware may then access the data in the header.随后的中间件可以访问标头中的数据。

func (server Server) ReadBody(h http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        body, _ := ioutil.ReadAll(r.Body)
        w.Header().Add("body", string(body))
        h.ServeHTTP(w, r) //Calls handler h
        w.Header().Del("body")
    })
}

Subsequent middleware will get the body data with the instruction data := w.Header().Get("body") .后续中间件将使用指令data := w.Header().Get("body")正文数据。 Note that a header value is a string, not a byte slice.请注意,标头值是一个字符串,而不是字节切片。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM