猿问

转到 HTTP 请求 POST 标头,等待响应,然后发布分块的正文内容

我试图弄清楚是否有办法将分块数据发布到 HTTP 服务器,该服务器在接受我的任何请求正文之前尝试发送标头。


我有一个服务器,它通过 POST 请求接收永无止境的数据流。收到新的 POST 请求后,它会构造标头并立即尝试刷新。


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {

    requestId := uuid.Must(uuid.NewV4()).String()


    w.Header().Set("X-Request-Id", requestId)

    w.Header().Set("Content-Type", "application/octet-stream")


    client := &Connection{requestId, make(chan []byte, 50), r, w}

    defer client.Request.Body.Close()


    switch client.Request.Method {

        case http.MethodPost:

            client.Writer.(http.Flusher).Flush()

            // goes on to read data from the connection until it is closed

    }

}

这适用于使用套接字实现的 POST 客户端,它可以决定在实际发送任何正文数据之前读取服务器响应。但是,我无法弄清楚如何让它为 Go http Request 对象工作。


在客户端,我有一个正在将数据写入 io.PipeWriter 的 goroutine,并且我已将 PipeReader (pr) 传递给 Request 对象:


req := &http.Request{

    Method: "POST",   

    ProtoMajor: 1,    

    ProtoMinor: 1,    

    URL: serverUrl,

    TransferEncoding: []string{"chunked"},

    Body: pr,

    Header: make(map[string][]string),

}


resp, err := http.DefaultClient.Do(req)

这在两端永远挂起,因为 PipeReader 永远不会关闭,并且服务器在 Flush 上阻塞。我想做的是发送标题,等待服务器的响应,然后开始发送正文内容。


我试过只是不在BodyRequest 对象中包含,这会发送标头,接收响应标头,并且连接似乎保持打开状态。但是从我所有的阅读来看,我似乎无法找到一种方法来通过这个连接发送额外的数据。


当然,我可以不在服务器端刷新并处理数据——但我实际上正在实现一个指定此行为的协议,因此现有的客户端软件不会发送正文数据,除非它首先收到响应标头。


一只萌萌小番薯
浏览 75回答 1
1回答

精慕HU

所以服务器在 Flush 中阻塞,因为主体仍然是打开的。事实证明,如果您在客户端的 POST 请求中将Connection标头设置为close(编辑:您可以在刷新之前在服务器响应标头中设置它,并且无论客户端在做什么,它都有效),服务器将忽略主体仍然存在的事实无论如何打开并刷新(并保持连接打开以读取数据)。整洁的。我似乎无法在描述此行为的 HTTP 规范或 Go http 库中找到任何文档。但我们到了。
随时随地看视频慕课网APP

相关分类

Go
我要回答