2009-04-20 22 views
21

Tengo un código simple que hace una solicitud principal de una URL y luego imprime los encabezados de respuesta. Me di cuenta de que en algunos sitios esto puede llevar mucho tiempo en completarse. Por ejemplo, solicitar http://www.arstechnica.com lleva unos dos minutos. He intentado la misma solicitud usando otro sitio web que hace la misma tarea básica, y vuelve de inmediato. Entonces debe haber algo que haya configurado incorrectamente que está causando este retraso.PHP/Curl: solicitud HEAD tarda mucho tiempo en algunos sitios

Aquí está el código que tengo:

$ch = curl_init(); 
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt ($ch, CURLOPT_URL, $url); 
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 20); 
curl_setopt ($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); 

// Only calling the head 
curl_setopt($ch, CURLOPT_HEADER, true); // header will be at output 
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'HEAD'); // HTTP request is 'HEAD' 

$content = curl_exec ($ch); 
curl_close ($ch); 

Aquí hay un enlace a la página web que hace la misma función: http://www.seoconsultants.com/tools/headers.asp

El código anterior, al menos en mi servidor, toma dos minutos para recuperar www.arstechnica.com, pero el servicio en el enlace de arriba lo devuelve de inmediato.

¿Qué me estoy perdiendo?

+1

lo _curl_ falta es un cuerpo de la respuesta, que no sabe que las peticiones HEAD sólo devuelven cabeceras (sin cuerpo) por lo que está en espera en el servidor para enviar más datos. así que el curl espera 2 minutos y luego se da por vencido. – Jasen

Respuesta

41

intente simplificar un poco:

print htmlentities(file_get_contents("http://www.arstechnica.com")); 

Las salidas anteriores al instante en mi servidor web. Si no es así, es muy probable que su proveedor de alojamiento web tenga algún tipo de configuración para limitar este tipo de solicitudes.

EDITAR:

Dado lo anterior sucede al instante para usted, intente establecer this curl setting en su código original:

curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, true); 

Con la herramienta informados, me di cuenta de que http://www.arstechnica.com tiene una cabecera 301 enviado para cualquier solicitud que se le envíe. Es posible que cURL esté obteniendo esto y no siga la nueva ubicación especificada, lo que hace que su script se bloquee.

SEGUNDA EDICIÓN:

Curiosamente, tratando el mismo código que haya más arriba estaba haciendo mi servidor web colgar también. He sustituido este código:

curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'HEAD'); // HTTP request is 'HEAD' 

Con esta:

curl_setopt($ch, CURLOPT_NOBODY, true); 

Cuál es la forma the manual recomienda que hagas una petición HEAD. Lo hizo funcionar al instante.

+0

que emite el código html de www.arstechnica.com al instante. – Ian

+0

sin cambios, lamentablemente. – Ian

+0

y estoy tratando de recuperar solo los encabezados de respuesta de la primera página, y no más adelante en la línea. – Ian

2

Si mi memoria no me falla haciendo una petición HEAD en CURL cambia la versión del protocolo HTTP a 1.0 (que es lento y probablemente la parte culpable aquí) intenta cambiar eso para:

$ch = curl_init(); 
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt ($ch, CURLOPT_URL, $url); 
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 20); 
curl_setopt ($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); 

// Only calling the head 
curl_setopt($ch, CURLOPT_HEADER, true); // header will be at output 
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'HEAD'); // HTTP request is 'HEAD' 
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); // ADD THIS 

$content = curl_exec ($ch); 
curl_close ($ch); 
+0

parece estar usando HTTP 1.1 de forma predeterminada, al menos de acuerdo con la respuesta que finalmente obtengo: HTTP/1.1 301 Se movió permanentemente en cualquier caso, agregando que la línea no tiene efecto. – Ian

6

Tienes recordar que HEAD es solo una sugerencia para el servidor web. Para que HEAD haga lo correcto, a menudo requiere un esfuerzo explícito por parte de los administradores. Si ESCUCHA un archivo estático Apache (o lo que sea que sea su servidor web) a menudo hará un paso para hacer lo correcto. Si encabeza una página dinámica, la configuración predeterminada para la mayoría de las configuraciones es ejecutar la ruta GET, recopilar todos los resultados y simplemente devolver los encabezados sin el contenido.Si esa aplicación está en una configuración de nivel 3 (o más), esa llamada podría ser muy costosa e innecesaria para un contexto HEAD. Por ejemplo, en un servlet de Java, de manera predeterminada doHead() solo llama a doGet(). Para hacer algo un poco más inteligente para la aplicación, el desarrollador debería implementar explícitamente doHead() (y la mayoría de las veces no lo hará).

Encontré una aplicación de una compañía Fortune 100 que se utiliza para descargar varios cientos de megabytes de información de precios. Comprobamos las actualizaciones de esos datos ejecutando las solicitudes HEAD con bastante regularidad hasta que cambie la fecha de modificación. Resulta que esta solicitud en realidad haría llamadas back-end para generar esta lista cada vez que hiciéramos la solicitud que involucraba gigabytes de datos en su back-end y la transfiriera entre varios servidores internos. No estaban muy contentos con nosotros, pero una vez que explicamos el caso de uso, rápidamente se les ocurrió una solución alternativa. Si hubieran implementado HEAD, en lugar de confiar en su servidor web para simularlo, no habría sido un problema.

0

Este:

curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); 

yo no estaba tratando de obtener las cabeceras.
Estaba tratando de hacer que la carga de la página de algunos datos no tome 2 minutos similar a la descrita anteriormente.
Las pequeñas opciones mágicas se han reducido a 2 segundos.

3

Utilicé la función siguiente para averiguar la URL redirigida.

$head = get_headers($url, 1); 

El segundo argumento hace que devuelva una matriz con las teclas. Por ej. el siguiente dará el valor Location.

$head["Location"] 

http://php.net/manual/en/function.get-headers.php

+1

Tenga en cuenta que, si bien esta función utiliza una solicitud GET de forma predeterminada, puede configurarla para usar una solicitud HEAD (para reducir la sobrecarga al no recuperar una página completa, si corresponde) con las funciones de flujo_contexto de PHP. Un ejemplo se proporciona en la entrada manual. – Synexis

Cuestiones relacionadas