猿问

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

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


开始:


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

    })

}


慕神8447489
浏览 87回答 1
1回答

DIEA

只能r.Body读取一次。没有其他办法了。如果多个中间件需要访问数据,则需要将其保存为字节片并将其传递给后续中间件。如果处理程序有上下文,您可以将正文数据作为上下文中的值传递。另一种解决方案是 hack,是将数据存储在 ReponseWriter 的标头字段中。您不应忘记在返回时将其删除,以免将其发送出去。随后的中间件可以访问标头中的数据。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")。请注意,标头值是字符串,而不是字节切片。
随时随地看视频慕课网APP

相关分类

Go
我要回答