headers - PHP/Curl: HEAD Request tarda mucho tiempo en algunos sitios
php curl post (5)
Tengo un código simple que hace una solicitud principal para 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
dura 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.
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 al sitio 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?
Debes 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 de 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.
Esta:
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
No estaba tratando de obtener encabezados.
Solo estaba intentando hacer que la carga de la página de algunos datos no tome 2 minutos, como se describe arriba.
Esa pequeña y mágica opción ha bajado a 2 segundos.
Intenta simplificarlo un poco:
print htmlentities(file_get_contents("http://www.arstechnica.com"));
Lo anterior se produce 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 :
Como lo anterior sucede de manera instantánea para usted, intente configurar esta configuración de curvatura en su código original:
curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, true);
Usando la herramienta que publicaste, noté que http://www.arstechnica.com
tiene un encabezado 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 EDICION
Curiosamente, intentar el mismo código que tienes arriba también hacía que mi servidor web se cuelgue. Reemplacé este código:
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, ''HEAD''); // HTTP request is ''HEAD''
Con este:
curl_setopt($ch, CURLOPT_NOBODY, true);
Que es la forma en que el manual recomienda hacer una solicitud HEAD. Lo hizo funcionar al instante.
Si mi memoria no me falla haciendo una solicitud HEAD en CURL cambia la versión del protocolo HTTP a 1.0 (que es lenta y probablemente la parte culpable aquí) intente cambiar eso a:
$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);
Utilicé la función siguiente para descubrir la URL redirigida.
$head = get_headers($url, 1);
El segundo argumento hace que devuelva una matriz con claves. Por ejemplo, lo siguiente dará el valor de Location
.
$head["Location"]