http - 当请求有正文时,Go http 上下文无法捕获取消信号(curl, postman )

标签 http go curl postman

问题可以通过下面简单的go代码片段重现:

简单的 go http 服务器:

package main

import (
    "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))
}

在 http 服务器上启动,如果我发送一个简单的 GET使用 curl 请求(也包括 postman ),例如:

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 '{}'

总结一下我的问题:

  1. 为什么以及如何 curl ( postman )GET , POST (有或没有请求正文)请求有这么大的不同吗?
  2. 我应该如何使用 go 上下文包正确处理这种情况,我的意思是尽快捕获客户端已消失的信号,并进一步取消服务器端不必要的工作以尽早释放资源。

最佳答案

读取请求正文以检测客户端何时关闭连接:

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 服务器通过读取连接来检查关闭的连接。在应用程序开始读取请求正文(如果有)之前,不会开始读取。

关于http - 当请求有正文时,Go http 上下文无法捕获取消信号(curl, postman ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57246852/

相关文章:

go - GRPC 中的请求是如何处理的?

mysql - 如何处理 Golang 中插入重复键的错误?

RCurl::getURL 超出最大客户端数量

linux - 如何使用linux命令行计算某些网页上的图像加载时间?

javascript - 允许在 iframe 中混合内容

node.js - Puppeteer 与 Express Router Node JS 的并行性。如何在保持并发的情况下在路由之间传递页面

postgresql - 关于带变量的 Go sql 查询,我没有得到什么?

python - Flask 错误处理 : "Response object is not iterable"

java - 使用逗号分隔和多个参数创建 Rest url

java - 如果服务器没有响应,超时不起作用