Cómo establecer el tiempo de espera para http.Get () solicitudes en Golang?


Estoy haciendo una búsqueda de URL en Go y tengo una lista de URL para obtener. Envío http.Get() solicitudes a cada URL y obtengo su respuesta.

resp,fetch_err := http.Get(url)

¿Cómo puedo establecer un tiempo de espera personalizado para cada solicitud Get? (El tiempo predeterminado es muy largo y eso hace que mi recuperador sea muy lento.) Quiero que mi recuperador tenga un tiempo de espera de alrededor de 40-45 segundos después de lo cual debería devolver "request timed out" y pasar a la siguiente URL.

¿Cómo puedo lograr esto?

Author: pymd, 2013-06-03

6 answers

Aparentemente en Go 1.3 http.Cliente tiene campo de tiempo de espera

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

Eso ha hecho el truco para mí.

 197
Author: sparrovv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-03 12:12:42

Necesita configurar su propio Cliente con su propio Transporte que utiliza un función de marcación personalizada que envuelve DialTimeout .

Algo así como (completamente no probado) esto:

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")
}
 52
Author: Volker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-03 11:40:24

Para agregar a la respuesta de Volker, si también desea establecer el tiempo de espera de lectura/escritura además del tiempo de espera de conexión, puede hacer algo como lo siguiente

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

Este código se prueba y está funcionando en producción. El resumen completo con las pruebas está disponible aquí https://gist.github.com/dmichael/5710968

Tenga en cuenta que tendrá que crear un nuevo cliente para cada solicitud debido a la conn.SetDeadline que hace referencia a un punto en el futuro de time.Now()

 27
Author: dmichael,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-03 12:13:19

Un camino rápido y sucio:

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

Esto es estado global mutante sin ninguna coordinación. Sin embargo, es posible que esté bien para su url fetcher. De lo contrario, cree una instancia privada 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)
...

Nada de lo anterior fue probado.

 8
Author: zzzz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-03 11:36:04

Puede usar https://github.com/franela/goreq que maneja los tiempos de espera de una manera sencilla.

 1
Author: marcosnils,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-21 19:42:44

Si desea hacerlo por solicitud, err manejo ignorado por brevedad:

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))
 1
Author: Chad Grant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-27 21:41:47