[英]Redirects return http: multiple response.WriteHeader calls
I am using Jon Calhoun's Go MVC framework from github. 我正在使用来自github的Jon Calhoun的Go MVC框架 。
The framework uses julienschmidt/httprouter as its only dependency. 该框架使用julienschmidt / httprouter作为其唯一依赖项。
I have a similar main method as found in the example: 我有一个与示例类似的主要方法:
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))
}
I make a post to the login url, and it calls the following method: 我在登录网址中发布了一个帖子,它调用了以下方法:
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))
}
Basically, if the login was not correct I return the same view. 基本上,如果登录不正确,我将返回相同的视图。 If the login is correct I want to redirect to another method in a different controller.
如果登录正确,我想重定向到另一个控制器中的另一个方法。
However when I call http.Redirect(w, r, "/dashboard", 307)
, it returns the following error: 但是,当我调用
http.Redirect(w, r, "/dashboard", 307)
,它返回以下错误:
http: multiple response.WriteHeader calls
I'm not sure exactly why this is happening, but I suspect that it has something to do with my listener calling the Perform function, which creates a http.handler, as shown below. 我不确定为什么会这样,但是我怀疑这与我的监听器调用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)
}
})
}
Does anyone have any idea how to redirect using this MVC framework? 有谁知道如何使用此MVC框架进行重定向? Or have a one off solution?
还是有一个一次性解决方案?
http.ResponseWriter 's WriteHeader
method can only be called once per HTTP response, for obvious reasons: You can only have a single response code, and you can only send the headers once. 每个HTTP响应只能调用一次http.ResponseWriter的
WriteHeader
方法,原因很明显:您只能有一个响应代码,并且只能发送标头一次。
The error you see means that it is called a second time on the same response. 您看到的错误意味着在同一响应上第二次被调用。
Your middleware calls: 您的中间件调用:
w.WriteHeader(200)
Then your handler also calls: 然后,您的处理程序还会调用:
http.Redirect(w, r, "/dashboard", 307)
log.Println("-----")
return views.Dashboard.Index.Render(w, login, helpers.AcceptsGzip(r))
Your middleware should never call WriteHeader
, until after the fate of the response is known. 您的中间件永远不要调用
WriteHeader
,直到知道响应的命运。
Further, without knowing about your particular MVC framework, it seems possible that after you send the 307
status, then you also tell the MVC framework to render a response, which may also call WriteHeader
again. 此外,在不了解特定MVC框架的情况下,似乎有可能在发送
307
状态之后,您还告诉MVC框架呈现响应,这也可能再次调用WriteHeader
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.