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

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

我有一个基本的中间件,它是一个 Logger 函数,当我在接下来的每个函数中执行 body, err := ioutil.ReadAll(r.Body) 时,http.Request 将为空。但我希望 body 包含信息。我能做什么?

开始:

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

所以是中间件:

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

现在 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))
    })
}

r.Body只能读取一次。没有其他办法了。

如果多个中间件需要访问数据,则需要将其保存一个字节片,传递给后续的中间件。

如果处理程序有上下文,您可以将 body 数据作为上下文中的值传递。

另一种解决方案是 hack,将数据存储在 ReponseWriter 的 header 字段中。退货时不要忘记取下,以免寄出。随后的中间件可能会访问 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")
    })
}

后续中间件会通过指令data := w.Header().Get("body")获取body数据。请注意,header 值是一个字符串,而不是字节片。