147 votes

Comment définir le délai d'attente pour le http.Get() demandes de golang?

Je suis en train de faire un url de l'outil de récupération en aller et avoir une liste d'url pour récupérer. - Je envoyer http.Get() les demandes de chaque url et obtenir leur réponse.

resp,fetch_err := http.Get(url)

Comment puis-je définir un délai d'expiration personnalisée pour chaque requête Get? (La valeur par défaut est très long, ce qui rend mon outil de récupération très lente.) Je veux que mon récupérateur d'avoir un délai d'attente d'environ 40-45 secondes après lesquelles il doit retourner "request timed out" et de passer à côté de l'url.

Comment puis-je y parvenir?

324voto

sparrovv Points 1584

Apparemment en aller 1.3 http.Le Client dispose du Délai d'attente de terrain

timeout := time.Duration(5 * time.Second)
client := http.Client{
    Timeout: timeout,
}
client.Get(url)

C'est ce que fait le truc pour moi.

54voto

Volker Points 6807

Vous devez configurer votre propre Client avec votre propre Transport qui utilise un la coutume de la fonction de Numérotation qui s'enroule autour de DialTimeout.

Quelque chose comme (complètement non testé) ce:

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")
}

34voto

dmichael Points 420

Pour ajouter à Volker réponse, si vous souhaitez également définir la lecture/écriture de délai d'attente en plus du délai de connexion vous pouvez faire quelque chose comme ce qui 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 de travail dans la production. La pleine gist avec des tests sont disponibles ici https://gist.github.com/dmichael/5710968

Sachez que vous aurez besoin de créer un nouveau client pour chaque demande en raison de la conn.SetDeadline qui fait référence à un point dans l'avenir, de temps.Maintenant()

11voto

zzzz Points 23017

Une façon rapide et sale:

http.DefaultTransport.(*http.Transport).ResponseHeaderTimeout = time.Second * 45

C'est la mutation de l'état global w/o de la coordination. Pourtant, il pourrait être peut-être correct pour votre url de l'outil de récupération. Autrement créer 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 a été testé.

1voto

marcosnils Points 81

Vous pouvez utiliser https://github.com/franela/goreq qui gère les délais d'attente dans une de la mode et de la manière la plus simple.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X