dongxian4531 2016-03-30 18:06
浏览 211
已采纳

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

I've been trying to solve a weird problem for quite some time now. After stepping through lots of angular code, I noticed something weird while logging requests to my server through Charles.

When I post to a url /myurl the request never actually hits my server. Instead, it gets a 301 response and THEN a GET request hite my server.

This is incredibly puzzling. Has anyone else run into this problem? I've uploaded a screenshot of my Charles log incase you are interested.

enter image description here

Just as a reference, this is what my server looks like:

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()+"

")
    }
    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)
}
  • 写回答

1条回答 默认 最新

  • doudou6719 2016-03-30 18:23
    关注

    The explanation is simple: because you used the "/myurl/" path when you registered your PHandler (note the trailing slash /!) but you directed your browser to /myurl (note there is no trailing slash). And by default the http package implementation will perform (send back) a redirect request so if the browser follows it (it will), the new URL will match the registered path.

    This is documented at type http.ServeMux:

    If a subtree has been registered and a request is received naming the subtree root without its trailing slash, ServeMux redirects that request to the subtree root (adding the trailing slash). This behavior can be overridden with a separate registration for the path without the trailing slash. For example, registering "/images/" causes ServeMux to redirect a request for "/images" to "/images/", unless "/images" has been registered separately.

    Should you direct your browser directly to /myurl/, you would not experience a redirect.

    Or if you don't need to handle a rooted subtree but only a single path (e.g. /myurl), then register your handler only to this single path:

    http.HandleFunc("/myurl", PHandler)
    

    And then of course direct your browser to /myurl, and you will not experience any redirect either.

    ...Or as the documentation suggests: register both paths to your handler if you really need it:

    http.HandleFunc("/myurl", PHandler)
    http.HandleFunc("/myurl/", PHandler)
    

    And now no matter which path you call (/myurl or /myurl/), both will result in calling your handler without any redirection taking place.

    Notes:

    In your situation when a redirect was sent back to the browser, the browser will not repeat the POST request (but rather just a "simple" GET request).

    Generally speaking a browser will not send POST data to a redirect URL because the browser is not qualified to decide if you're willing to send the same data to the new URL what you intended to send to the original URL (think about passwords, credit card numbers and other sensitive data). But don't try to circumvent it, simply use registered path of your handler to POST to, or any of the other tips mentioned above.

    You can read more on the subject here:

    Why doesn't HTTP have POST redirect?

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘