我正在使用golang向服务器发出http post请求。假设服务器当前已关闭(表示服务器运行的机器已关闭),则请求将停留在IP层。所以我的程序执行无法继续进行。它无法进入应用程序层。那么golang有什么方法可以阻止它。 我使用以下代码。
req, err := http.NewRequest("POST", url, bytes.NewReader(b))
if err != nil {
return errors.Wrap(err, "new request error")
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return errors.Wrap(err, "http request error")
}
defer resp.Body.Close()
是否可以添加任何内容,以便在请求无法从IP层找到任何内容时终止请求。
答案 0 :(得分:2)
默认的http客户端没有超时。您可以自己创建一个显式的http.Client并设置超时:
var cl = &http.Client{
Timeout: time.Second * 10,
}
resp, err := cl.Do(req)
if err != nil {
// err will be set on timeout
return errors.Wrap(err, "http request error")
}
defer resp.Body.Close()
如果服务器在请求中间不再应答,则可以处理超时。
答案 1 :(得分:1)
在这种情况下,运输@kostix指的是你正在寻找的。运输和客户也可以安全地同时使用。但请read about the Transport(我也建议阅读有关客户端的内容),因为有许多不同的方法可以影响您处理空闲连接的方式,而不仅仅是前面提到的DialContext。
您可能想要设置ResponseHeaderTimeout
:
ResponseHeaderTimeout,如果非零,则指定数量 完全等待服务器响应头的时间 写请求(包括其正文,如果有的话)。这个 时间不包括阅读回应正文的时间。
或者,如果您使用的是安全连接,则可能需要设置TLSHandshakeTimeout
:
TLSHandshakeTimeout指定等待的最长时间 等待TLS握手。零意味着没有超时。
为了便于阅读和维护,我建议也可以创建一个构建客户端的功能,类似于:
func buildClient(timeout time.Duration) *http.Client {
tr := &http.Transport{
IdleConnTimeout: timeout,
ResponseHeaderTimeout: timeout,
TLSHandshakeTimeout: timeout,
}
client := &http.Client{
Transport: tr,
Timeout: timeout,
}
return client
}
答案 2 :(得分:0)
使用非http.Transport
的{{1}}字段设置为一个函数,该函数使用具有正确配置的超时/截止时间的自定义上下文。另一种选择是使用自定义DialContext
。
这样的事情:
net.Dialer
请注意,根据cli := http.Client{
Transport: &http.Transport{
DialContext: func (ctx context.Context, network, address string) (net.Conn, error) {
dialer := net.Dialer{
Timeout: 3 * time.Second,
}
return dialer.DialContext(ctx, network, address)
},
},
}
req, err := http.NewRequest(...)
resp, err := cli.Do(req)
的文档,传递给其net.Dialer
的上下文可能胜过拨号器本身设置的超时 - 这是
正是我们需要的:拨号器的DialContext
字段完全控制
“拨号”(TCP连接建立),你也可以武装你的
带有上下文(使用Timeout
)控制的HTTP请求
整个请求的超时,也可以随时取消(包括拨号步骤)。