2016-03-30 123 views
4

我一直试图解决weird problem很长时间了。在通过大量的角码之后,我通过Charles向我的服务器记录请求时发现了一些奇怪的事情。Go Web服务器自动重定向POST请求

当我张贴到一个网址/myurl请求从来没有真正命中我的服务器。相反,它得到一个301响应,然后GET请求发送我的服务器。

这令人难以置信的令人费解。有其他人遇到这个问题吗?我已经上传了我对Charles感兴趣的Charles日志的屏幕截图。

enter image description here

只是作为参考,这是我的服务器上的样子:

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) 
} 

回答

11

原因很简单:因为您在注册您的PHandler(注意尾随斜线使用"/myurl/"路径/!),但是您将浏览器指向了/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数据发送到重定向URL,因为浏览器没有资格决定是否愿意将相同的数据发送到新URL您打算发送到原始URL(想想关于密码,信用卡号码和其他敏感数据)。但是不要试图规避它,仅仅使用你的处理程序的注册路径来POST,或者上面提到的其他任何提示。

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

Why doesn't HTTP have POST redirect?

+0

为什么ServeMux重定向得到什么?为什么不使用原始请求的方法?更重要的是,有没有办法让这个重定向执行POST? – dopatraman

+0

@dopatraman查看编辑答案(实际上将它添加到答案中,因为它对其他人来说也是信息)。 – icza

+0

谢谢。如果您将此答案添加到此主题(http://stackoverflow.com/questions/36295758/http-post-method-is-actally-sending-a-get),我也会将其标记为正确。 – dopatraman