Je crée un récupérateur d'URL dans Go et une liste des URL à récupérer. J'envoie des requêtes http.Get()
à chaque URL et j'obtiens leur réponse.
resp,fetch_err := http.Get(url)
Comment définir un délai d'expiration personnalisé pour chaque demande Get? (Le temps par défaut est très long et mon récupérateur est très lent.) Je souhaite que le récupérateur ait un délai d'attente d'environ 40 à 45 secondes après lequel il doit renvoyer "requête expirée" et passer à l'URL suivante.
Comment puis-je atteindre cet objectif?
Apparemment, dans Go 1.3 http.Client a un champ Timeout
timeout := time.Duration(5 * time.Second)
client := http.Client{
Timeout: timeout,
}
client.Get(url)
Cela a fait le tour pour moi.
Vous devez configurer votre propre Client avec votre propre Transport qui utilise une fonction de numérotation personnalisée qui enveloppe DialTimeout .
Quelque chose comme (complètement non testé ) 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")
}
Pour ajouter à la réponse de Volker, si vous souhaitez également définir le délai de lecture/écriture en plus du délai de connexion, vous pouvez procéder comme suit:
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),
},
}
}
Ce code est testé et fonctionne en production. Le Gist complet avec les tests est disponible ici https://Gist.github.com/dmichael/5710968
Sachez que vous devrez créer un nouveau client pour chaque demande en raison du conn.SetDeadline
Qui fait référence à un point futur de time.Now()
.
Si vous voulez le faire par requête, la gestion des erreurs est ignorée par souci de concision:
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))
Un moyen rapide et sale:
http.DefaultTransport.(*http.Transport).ResponseHeaderTimeout = time.Second * 45
C’est un état mondial en mutation, sans aucune coordination. Pourtant, cela pourrait peut-être bien se passer pour votre récupérateur d’URL. Sinon, créez une instance privée de 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)
...
Rien ci-dessus n'a été testé.
Vous pouvez utiliser https://github.com/franela/goreq , qui gère les délais d'attente de manière simple et simple.
timeout := time.Duration(5 * time.Second)
transport := &http.Transport{Proxy: http.ProxyURL(proxyUrl), ResponseHeaderTimeout:timeout}
Cela peut aider, mais notez que ResponseHeaderTimeout
ne commence que lorsque la connexion est établie.