如何过早关闭/中止Golang http.Client POST [英] how to close/abort a Golang http.Client POST prematurely
问题描述
我正在将 http.Client
用于客户端的长轮询:
I'm using http.Client
for the client-side implementation of a long-poll:
resp, err := client.Post(url, "application/json", bytes.NewBuffer(jsonPostBytes))
if err != nil {
panic(err)
}
defer resp.Body.Close()
var results []*ResponseMessage
err = json.NewDecoder(resp.Body).Decode(&results) // code blocks here on long-poll
是否有一种标准方法可以从客户端抢占/取消请求?
我想调用resp.Body.Close()
可以做到这一点,但是我不得不从另一个goroutine调用它,因为通常在读取长轮询的响应时,客户端已经被阻塞了.
I imagine that calling resp.Body.Close()
would do it, but I'd have to call that from another goroutine, as the client is normally already blocked in reading the response of the long-poll.
我知道有一种方法可以通过http.Transport
设置超时,但是我的应用逻辑需要根据用户操作(不仅是超时)进行取消操作.
I know that there is a way to set a timeout via http.Transport
, but my app logic need to do the cancellation based on a user action, not just a timeout.
推荐答案
不,client.Post是90%不需要取消请求的用例的便捷包装.
Nope, client.Post is a handy wrapper for 90% of use-cases where request cancellation is not needed.
只需重新实现客户端以访问具有CancelRequest()函数的基础传输对象,就足够了.
Probably it will be enough simply to reimplement your client to get access to underlying Transport object, which has CancelRequest() function.
一个简单的例子:
package main
import (
"log"
"net/http"
"time"
)
func main() {
req, _ := http.NewRequest("GET", "http://google.com", nil)
tr := &http.Transport{} // TODO: copy defaults from http.DefaultTransport
client := &http.Client{Transport: tr}
c := make(chan error, 1)
go func() {
resp, err := client.Do(req)
// handle response ...
_ = resp
c <- err
}()
// Simulating user cancel request channel
user := make(chan struct{}, 0)
go func() {
time.Sleep(100 * time.Millisecond)
user <- struct{}{}
}()
for {
select {
case <-user:
log.Println("Cancelling request")
tr.CancelRequest(req)
case err := <-c:
log.Println("Client finished:", err)
return
}
}
}
这篇关于如何过早关闭/中止Golang http.Client POST的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!