可以使用以下簡單的 go 代碼片段重現該問題:簡單的http服務器:package mainimport ( "fmt" "log" "net/http" "time")func handler(w http.ResponseWriter, r *http.Request) { go func(done <-chan struct{}) { <-done fmt.Println("message", "client connection has gone away, request got cancelled") }(r.Context().Done()) time.Sleep(30 * time.Second) fmt.Fprintf(w, "Hi there, I love %s!\n", r.URL.Path[1:])}func main() { http.HandleFunc("/", handler) log.Fatal(http.ListenAndServe(":8080", nil))}GET從http服務器上方開始,如果我使用curl(也有郵遞員)發送一個簡單的請求,例如:curl -X GET http://localhost:8080/然后按Ctrl+C終止請求,然后我可以在服務器端看到打印的消息:message client connection has gone away, request got cancelled以上是我期望的正確行為:模擬當客戶端消失時服務器可以捕獲它的情況,然后盡早取消所有不必要的工作。但是,當我發送一個帶有請求正文的 POST 請求時,這種預期的行為不會發生,<-done信號被捕獲,直到請求截止日期滿足。curl -X POST http://localhost:8080/ -H 'Content-Type: application/json' -d '{}'總結一下我的問題:為什么以及如何curl(postman) GET(POST帶或不帶請求正文)請求產生如此大的差異?我應該如何使用 go context 包正確處理這種情況,我的意思是盡快捕獲客戶端消失的信號,從而進一步取消服務器端不必要的工作以盡早釋放資源。
1 回答

慕勒3428872
TA貢獻1848條經驗 獲得超6個贊
讀取請求正文以檢測客戶端何時關閉連接:
func handler(w http.ResponseWriter, r *http.Request) {
go func(done <-chan struct{}) {
<-done
fmt.Println("message", "client connection has gone away, request got cancelled")
}(r.Context().Done())
io.Copy(ioutil.Discard, r.Body) // <-- read the body
time.Sleep(30 * time.Second)
fmt.Fprintf(w, "Hi there, I love %s!\n", r.URL.Path[1:])
}
net/http 服務器通過讀取連接來檢查關閉的連接。在應用程序開始讀取請求正文(如果有)之前,不會開始讀取。
- 1 回答
- 0 關注
- 120 瀏覽
添加回答
舉報
0/150
提交
取消