2016-03-30 256 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