GoでURLフェッチャーを作成しており、フェッチするURLのリストがあります。 http.Get()
リクエストを各URLに送信し、そのレスポンスを取得します。
resp,fetch_err := http.Get(url)
Getリクエストごとにカスタムタイムアウトを設定するにはどうすればよいですか? (デフォルトの時間は非常に長いため、フェッチャーは非常に遅くなります。)フェッチャーのタイムアウトを約40〜45秒にしてから、「リクエストがタイムアウトしました」を返し、次のURLに移動する必要があります。
どうすればこれを達成できますか?
Go 1.3ではどうやら http.Client にはタイムアウトフィールドがあります
timeout := time.Duration(5 * time.Second)
client := http.Client{
Timeout: timeout,
}
client.Get(url)
これでうまくいきました。
独自の Client を独自の Transport に設定する必要があります。これは DialTimeout をラップするカスタムダイヤル機能を使用します。
(completelyuntested)のようなもの this :
var timeout = time.Duration(2 * time.Second)
func dialTimeout(network, addr string) (net.Conn, error) {
return net.DialTimeout(network, addr, timeout)
}
func main() {
transport := http.Transport{
Dial: dialTimeout,
}
client := http.Client{
Transport: &transport,
}
resp, err := client.Get("http://some.url")
}
Volkerの答えに追加するには、接続タイムアウトに加えて読み取り/書き込みタイムアウトも設定したい場合は、次のようなことができます
package httpclient
import (
"net"
"net/http"
"time"
)
func TimeoutDialer(cTimeout time.Duration, rwTimeout time.Duration) func(net, addr string) (c net.Conn, err error) {
return func(netw, addr string) (net.Conn, error) {
conn, err := net.DialTimeout(netw, addr, cTimeout)
if err != nil {
return nil, err
}
conn.SetDeadline(time.Now().Add(rwTimeout))
return conn, nil
}
}
func NewTimeoutClient(connectTimeout time.Duration, readWriteTimeout time.Duration) *http.Client {
return &http.Client{
Transport: &http.Transport{
Dial: TimeoutDialer(connectTimeout, readWriteTimeout),
},
}
}
このコードはテスト済みで、本番環境で動作しています。テスト付きの完全なGistはここから入手できます https://Gist.github.com/dmichael/5710968
time.Now()
から将来のポイントを参照するconn.SetDeadline
があるため、リクエストごとに新しいクライアントを作成する必要があることに注意してください
リクエストごとに実行する場合、簡潔にするためにエラー処理は無視されます。
ctx, cncl := context.WithTimeout(context.Background(), time.Second*3)
defer cncl()
req, _ := http.NewRequest(http.MethodGet, "https://google.com", nil)
resp, _ := http.DefaultClient.Do(req.WithContext(ctx))
迅速で汚い方法:
http.DefaultTransport.(*http.Transport).ResponseHeaderTimeout = time.Second * 45
これは、調整なしでグローバル状態を変化させています。それでも、URLフェッチャーにとっては大丈夫かもしれません。それ以外の場合は、http.RoundTripper
のプライベートインスタンスを作成します。
var myTransport http.RoundTripper = &http.Transport{
Proxy: http.ProxyFromEnvironment,
ResponseHeaderTimeout: time.Second * 45,
}
var myClient = &http.Client{Transport: myTransport}
resp, err := myClient.Get(url)
...
上記のテストは行われていません。
https://github.com/franela/goreq を使用することができます。これは、タイムアウトを簡単な方法で処理します。
timeout := time.Duration(5 * time.Second)
transport := &http.Transport{Proxy: http.ProxyURL(proxyUrl), ResponseHeaderTimeout:timeout}
これは役立つかもしれませんが、ResponseHeaderTimeout
は接続が確立された後にのみ開始されることに注意してください。