我一直试图解决weird problem已经有一段时间了。在经过大量的角度代码之后,我注意到在通过Charles将请求记录到我的服务器时有些奇怪。
当我发布到网址/myurl
时,请求实际上从未到达我的服务器。相反,它得到301响应,然后GET请求hite我的服务器。
令人难以置信的令人费解。有没有其他人遇到这个问题?我已经上传了我感兴趣的查尔斯日志的截图。
作为参考,这就是我的服务器的样子:
type FormStruct struct {
Test string
}
func PHandler(w http.ResponseWriter, r *http.Request) {
var t FormStruct
req, _ := httputil.DumpRequest(r, true)
log.Println(string(req))
log.Println(r.Method) // GET
log.Println(r.Body)
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(&t)
log.Println("Decoding complete")
if err != nil {
log.Println("Error")
panic(err.Error()+"\n\n")
}
log.Println(t.Test)
w.Write([]byte("Upload complete, no errors"))
}
func main() {
http.HandleFunc("/myurl/", PHandler)
fmt.Println("Go Server listening on port 8001")
http.ListenAndServe(":8001", nil)
}
答案 0 :(得分:13)
解释很简单:因为您在注册"/myurl/"
时使用了PHandler
路径(请注意尾部斜杠/
!),但您已将浏览器定向到/myurl
(注意没有斜杠)。默认情况下,http
包实现将执行(发回)重定向请求,因此如果浏览器跟随它(它将),新URL将与注册的路径匹配。
这在http.ServeMux
类型中记录:
如果已注册子树并且收到命名子树根但没有其斜杠的请求,则ServeMux会将该请求重定向到子树根(添加尾部斜杠)。可以覆盖此行为单独注册没有尾部斜杠的路径。例如,注册“/ images /”会导致ServeMux将“/ images”请求重定向到“/ images /”,除非“/ images”已单独注册。
如果您将浏览器直接定向到/myurl/
,则不会遇到重定向。
或者,如果您不需要处理有根的子树但只需要处理单个路径(例如/myurl
),那么只需将处理程序注册到此单一路径:
http.HandleFunc("/myurl", PHandler)
然后当然将浏览器定向到/myurl
,您也不会遇到任何重定向。
...或者正如文档建议的那样:如果你确实需要,请注册你的处理程序的两个路径:
http.HandleFunc("/myurl", PHandler)
http.HandleFunc("/myurl/", PHandler)
现在无论你调用哪条路径(/myurl
或/myurl/
),都会导致调用你的处理程序而不进行任何重定向。
备注:强>
在您将重定向发送回浏览器的情况下,浏览器不会重复POST请求(而只是“简单”的GET请求)。
一般来说,浏览器不会将POST数据发送到重定向网址,因为浏览器没有资格决定您是否愿意将相同的数据发送到您要发送到原始网址的新网址(请考虑一下密码,信用卡号码和其他敏感数据)。但是不要试图绕过它,只需使用你的处理程序的注册路径来POST,或者上面提到的任何其他技巧。
您可以在此处阅读有关此主题的更多信息: