net - http servefile
¿Cómo establecer el tiempo de espera para las solicitudes de http.Get() en Golang? (6)
Estoy haciendo una búsqueda de URL en Ir y tengo una lista de URL para buscar. http.Get()
solicitudes http.Get()
a cada URL y http.Get()
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 captura sea realmente lenta.) Quiero que mi captura tenga un tiempo de espera de alrededor de 40-45 segundos, después de lo cual debe devolver "tiempo de espera de solicitud agotado" y pasar a la siguiente URL.
¿Cómo puedo conseguir esto?
Al final, terminé usando esta función de utilidad para todas las solicitudes que requieren tiempo de espera. Por alguna razón, el código de @sparrovv estaba actuando.
// reqType is one of HTTP request strings (GET, POST, PUT, DELETE, etc.)
func DoRequest(reqType string, url string, headers map[string]string, data []byte, timeoutSeconds int) (int, []byte, map[string][]string, error) {
var reader io.Reader
if data != nil && len(data) > 0 {
reader = bytes.NewReader(data)
}
req, err := http.NewRequest(reqType, url, reader)
if err != nil {
return 0, nil, nil, err
}
// I strongly advise setting user agent as some servers ignore request without it
req.Header.Set("User-Agent", "YourUserAgentString")
if headers != nil {
for k, v := range headers {
req.Header.Set(k, v)
}
}
var (
statusCode int
body []byte
timeout time.Duration
ctx context.Context
cancel context.CancelFunc
header map[string][]string
)
timeout = time.Duration(time.Duration(timeoutSeconds) * time.Second)
ctx, cancel = context.WithTimeout(context.Background(), timeout)
defer cancel()
err = httpDo(ctx, req, func(resp *http.Response, err error) error {
if err != nil {
return err
}
defer resp.Body.Close()
body, _ = ioutil.ReadAll(resp.Body)
statusCode = resp.StatusCode
header = resp.Header
return nil
})
return statusCode, body, header, err
}
Aparentemente en Go 1.3 http.Client tiene un 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í.
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 está probado y está trabajando en producción. La esencia completa de las pruebas está disponible aquí https://gist.github.com/dmichael/5710968
Tenga en cuenta que deberá crear un nuevo cliente para cada solicitud debido a la línea conn.SetDeadline
que hace referencia a un punto en el futuro desde el momento. time.Now()
Puede usar https://github.com/franela/goreq que maneja los tiempos de espera de una manera simple y de moda.
Una manera rápida y sucia:
http.DefaultTransport.(*http.Transport).ResponseHeaderTimeout = time.Second * 45
Esto es un estado global mutante sin coordinación. Sin embargo, es posible que esté bien para su buscador de URL. 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 arriba fue probado.
DialTimeout configurar su propio http.Client con su propio Transport que utiliza una función de Marcación personalizada que envuelve DialTimeout .
Algo así como (completamente no probado ) 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")
}