Go Web服务器自动重定向POST请求

dop*_*man 5 http go

我一直试图解决一个奇怪的问题很长一段时间了.在单步执行大量角度代码后,我注意到在通过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)
}
Run Code Online (Sandbox Code Playgroud)

icz*_*cza 15

解释很简单:因为您"/myurl/"在注册时使用了路径PHandler(请注意尾部斜杠/!)但是您指示浏览器/myurl(注意没有斜杠).默认情况下,http包实现将执行(发回)重定向请求,因此如果浏览器跟随它(它将),新URL将与注册的路径匹配.

这记录在类型http.ServeMux:

如果已注册子树并且接收到命名子树根而没有其斜杠的请求,则ServeMux会将该请求重定向到子树根(添加尾部斜杠).可以通过单独注册没有尾部斜杠的路径来覆盖此行为.例如,注册"/ images /"会导致ServeMux将"/ images"请求重定向到"/ images /",除非"/ images"已单独注册.

如果您直接浏览浏览器/myurl/,则不会遇到重定向问题.

或者,如果您不需要处理有根的子树但只需要处理单个路径(例如/myurl),那么只需将处理程序注册到此单个路径:

http.HandleFunc("/myurl", PHandler)
Run Code Online (Sandbox Code Playgroud)

然后当然会引导您的浏览器/myurl,您也不会遇到任何重定向.

...或者如文档所示:如果确实需要,请将两个路径注册到处理程序:

http.HandleFunc("/myurl", PHandler)
http.HandleFunc("/myurl/", PHandler)
Run Code Online (Sandbox Code Playgroud)

现在无论你调用哪个路径(/myurl/myurl/),都会导致调用你的处理程序而不进行任何重定向.

笔记:

在您将重定向发送回浏览器的情况下,浏览器不会重复POST请求(而只是一个"简单的"GET请求).

一般来说,浏览器不会将POST数据发送到重定向URL,因为浏览器没有资格决定您是否愿意将相同的数据发送到您要发送到原始URL的新URL(考虑密码,信用卡)卡号和其他敏感数据).但是不要试图绕过它,只需使用你的处理程序的注册路径来POST,或者上面提到的任何其他提示.

你可以在这里阅读更多关于这个主题:

为什么HTTP没有POST重定向?