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

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 docker环境配置
  • ¥20 绿盟安全扫描--检测到目标站点存在javascript框架库漏洞
  • ¥30 Android STD快速启动
  • ¥15 如何使用simulink建立一个永磁同步直线电机模型?
  • ¥30 天体光谱图的的绘制并得到星表
  • ¥15 PointNet++的onnx模型只能使用一次
  • ¥20 西南科技大学数字信号处理
  • ¥15 有两个非常“自以为是”烦人的问题急期待大家解决!
  • ¥30 STM32 INMP441无法读取数据
  • ¥15 R语言绘制密度图,一个密度曲线内fill不同颜色如何实现