如何过早关闭/中止Golang http.Client POST [英] how to close/abort a Golang http.Client POST prematurely

查看:549
本文介绍了如何过早关闭/中止Golang http.Client POST的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆