可以使用以下简单的 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 关注
- 88 浏览
添加回答
举报
0/150
提交
取消