重定向 return http:多个 response.WriteHeader 调用
Redirects return http: multiple response.WriteHeader calls
我正在使用 github 的 Jon Calhoun's Go MVC framework。
该框架使用 julienschmidt/httprouter 作为其唯一的依赖项。
我有一个与示例中类似的主要方法:
func main() {
//register routes
router := httprouter.New()
//default
router.GET("/", controllers.Login.Perform(controllers.Login.Index))
//login
router.GET("/login", controllers.Login.Perform(controllers.Login.Login))
router.POST("/login", controllers.Login.Perform(controllers.Login.PostLogin))
//dashboard
router.GET("/dashboard", controllers.Dashboard.Perform(controllers.Dashboard.Index))
//listen and handle requests
log.Fatal(http.ListenAndServe(":"+helpers.ReadConfig("port_http"), router))
}
我对登录 url 创建了一个 post,它调用了以下方法:
func (self LoginController) PostLogin(w http.ResponseWriter, r *http.Request, ps httprouter.Params) error {
//create our api url
var url = helpers.ReadConfig("api") + "login"
//fill model to post
login := models.LoginModel{
Password: r.FormValue("password"),
Email: r.FormValue("username"),
}
//render json from model
bytes, err := json.Marshal(login)
if err != nil {
panic(err)
}
//post to the API helpers
var resp = helpers.ApiPost(url, r, string(bytes))
//check response if successful
if resp.Code != constants.ApiResp_Success {
//TODO: Handle API Errors
login.Password = ""
errors := make(map[int]string)
errors[1] = "Please provide valid credntials."
login.Common = models.CommonModel{
ErrorList: errors,
}
return views.Login.Index.Render(w, login, helpers.AcceptsGzip(r))
}
log.Println("---Redirect--")
http.Redirect(w, r, "/dashboard", 307)
log.Println("-----")
return views.Dashboard.Index.Render(w, login, helpers.AcceptsGzip(r))
}
基本上,如果登录不正确,我 return 同样的看法。如果登录正确,我想重定向到不同控制器中的另一个方法。
然而,当我调用 http.Redirect(w, r, "/dashboard", 307)
时,它 return 出现以下错误:
http: multiple response.WriteHeader calls
我不确定为什么会发生这种情况,但我怀疑这与我的侦听器调用 Perform 函数有关,该函数创建了一个 http.handler,如下所示。
func (c *Controller) Perform(a Action) httprouter.Handle {
return httprouter.Handle(
func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
//set response headers
//TODO: set appropriate responce headers
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Cache-Control", "public, max-age=0")
w.Header().Set("Token", "NOT-A-VALID-TOKEN")
w.WriteHeader(200)
if err := a(w, r, ps); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
})
}
有人知道如何使用这个 MVC 框架进行重定向吗?或者有一个一次性的解决方案?
http.ResponseWriter 的 WriteHeader
方法只能在每个 HTTP 响应中调用一次,原因很明显:您只能有一个响应代码,并且只能发送 headers一次。
您看到的错误意味着它在同一响应上被第二次调用。
您的中间件调用:
w.WriteHeader(200)
然后您的处理程序还会调用:
http.Redirect(w, r, "/dashboard", 307)
log.Println("-----")
return views.Dashboard.Index.Render(w, login, helpers.AcceptsGzip(r))
您的中间件永远不应调用 WriteHeader
,直到响应的命运已知。
此外,在不知道您的特定 MVC 框架的情况下,似乎有可能在您发送 307
状态之后,您还告诉 MVC 框架呈现响应,这也可能调用 WriteHeader
再次。
我正在使用 github 的 Jon Calhoun's Go MVC framework。
该框架使用 julienschmidt/httprouter 作为其唯一的依赖项。
我有一个与示例中类似的主要方法:
func main() {
//register routes
router := httprouter.New()
//default
router.GET("/", controllers.Login.Perform(controllers.Login.Index))
//login
router.GET("/login", controllers.Login.Perform(controllers.Login.Login))
router.POST("/login", controllers.Login.Perform(controllers.Login.PostLogin))
//dashboard
router.GET("/dashboard", controllers.Dashboard.Perform(controllers.Dashboard.Index))
//listen and handle requests
log.Fatal(http.ListenAndServe(":"+helpers.ReadConfig("port_http"), router))
}
我对登录 url 创建了一个 post,它调用了以下方法:
func (self LoginController) PostLogin(w http.ResponseWriter, r *http.Request, ps httprouter.Params) error {
//create our api url
var url = helpers.ReadConfig("api") + "login"
//fill model to post
login := models.LoginModel{
Password: r.FormValue("password"),
Email: r.FormValue("username"),
}
//render json from model
bytes, err := json.Marshal(login)
if err != nil {
panic(err)
}
//post to the API helpers
var resp = helpers.ApiPost(url, r, string(bytes))
//check response if successful
if resp.Code != constants.ApiResp_Success {
//TODO: Handle API Errors
login.Password = ""
errors := make(map[int]string)
errors[1] = "Please provide valid credntials."
login.Common = models.CommonModel{
ErrorList: errors,
}
return views.Login.Index.Render(w, login, helpers.AcceptsGzip(r))
}
log.Println("---Redirect--")
http.Redirect(w, r, "/dashboard", 307)
log.Println("-----")
return views.Dashboard.Index.Render(w, login, helpers.AcceptsGzip(r))
}
基本上,如果登录不正确,我 return 同样的看法。如果登录正确,我想重定向到不同控制器中的另一个方法。
然而,当我调用 http.Redirect(w, r, "/dashboard", 307)
时,它 return 出现以下错误:
http: multiple response.WriteHeader calls
我不确定为什么会发生这种情况,但我怀疑这与我的侦听器调用 Perform 函数有关,该函数创建了一个 http.handler,如下所示。
func (c *Controller) Perform(a Action) httprouter.Handle {
return httprouter.Handle(
func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
//set response headers
//TODO: set appropriate responce headers
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Cache-Control", "public, max-age=0")
w.Header().Set("Token", "NOT-A-VALID-TOKEN")
w.WriteHeader(200)
if err := a(w, r, ps); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
})
}
有人知道如何使用这个 MVC 框架进行重定向吗?或者有一个一次性的解决方案?
http.ResponseWriter 的 WriteHeader
方法只能在每个 HTTP 响应中调用一次,原因很明显:您只能有一个响应代码,并且只能发送 headers一次。
您看到的错误意味着它在同一响应上被第二次调用。
您的中间件调用:
w.WriteHeader(200)
然后您的处理程序还会调用:
http.Redirect(w, r, "/dashboard", 307)
log.Println("-----")
return views.Dashboard.Index.Render(w, login, helpers.AcceptsGzip(r))
您的中间件永远不应调用 WriteHeader
,直到响应的命运已知。
此外,在不知道您的特定 MVC 框架的情况下,似乎有可能在您发送 307
状态之后,您还告诉 MVC 框架呈现响应,这也可能调用 WriteHeader
再次。