我有一个基本的中间件,它是一个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))
})
}
答案 0 :(得分:0)
r.Body
只能读取一次。没有其他办法了。
如果需要多个中间件访问数据,则需要将其保存一个字节片并将其传递给后续的中间件。
如果处理程序具有上下文,则可以将主体数据作为上下文中的值传递。
另一种解决方案是破解,是将数据存储在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")
获取主体数据。请注意,标头值是一个字符串,而不是字节片。