2009-04-20 5 views
21

J'ai un code simple qui fait une demande de tête pour une URL, puis imprime les en-têtes de réponse. J'ai remarqué que sur certains sites, cela peut prendre beaucoup de temps.PHP/Curl: HEAD Request prend beaucoup de temps sur certains sites

Par exemple, la demande http://www.arstechnica.com prend environ deux minutes. J'ai essayé la même demande en utilisant un autre site Web qui fait la même tâche de base, et il revient immédiatement. Donc, il doit y avoir quelque chose que j'ai mal défini qui cause ce retard.

Voici le code que j'ai:

$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); 

Voici un lien vers le site Web qui fait la même fonction: http://www.seoconsultants.com/tools/headers.asp

Le code ci-dessus, au moins sur mon serveur, prend deux minutes pour récupérer www.arstechnica.com, mais le service sur le lien ci-dessus le renvoie tout de suite.

Qu'est-ce qui me manque?

+1

ce _curl_ manque est un corps de réponse, il ne sait pas que les requêtes HEAD ne renvoient que des en-têtes (pas de corps), de sorte qu'il est en attente sur le serveur pour envoyer plus de données. alors la boucle attend pendant 2 minutes, puis abandonne. – Jasen

Répondre

41

simplifiez un peu:

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

Les sorties au-dessus instantanément sur mon serveur web. Si ce n'est pas le cas, il y a de fortes chances que votre hébergeur dispose d'un certain type de paramètre pour limiter ce type de requêtes.

EDIT:

Depuis l'arrive ci-dessus instantanément pour vous, essayez de this curl setting sur votre code d'origine:

curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, true); 

aide de l'outil que vous avez posté, j'ai remarqué que http://www.arstechnica.com a une 301 tête envoyé pour toute demande qui lui est envoyée. Il est possible que cURL l'obtienne et ne suive pas le nouvel emplacement qui lui est spécifié, provoquant ainsi le blocage de votre script.

EDIT DEUXIÈME:

Assez curieusement, en essayant le même code que vous avez ci-dessus faisait pendre mon serveur web aussi. Je l'ai remplacé ce code:

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

Avec ceci:

curl_setopt($ch, CURLOPT_NOBODY, true); 

Quelle est la façon the manual vous recommande de faire une requête HEAD. Cela l'a fait fonctionner instantanément.

+0

qui génère instantanément le code html de www.arstechnica.com. – Ian

+0

pas de changement, malheureusement. – Ian

+0

et j'essaie de récupérer seulement les en-têtes de réponse de la première page, et pas plus loin sur la ligne. – Ian

2

Si ma mémoire ne me parvient pas à faire une demande de HEAD CURL modifie la version du protocole HTTP 1.0 (qui est lent et probablement la partie coupable ici) essayer de changer cela à:

$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

il semble utiliser HTTP 1.1 par défaut, au moins selon la réponse que je ne finissent par être: HTTP/1.1 301 Moved Permanently dans tous les cas, l'ajout de cette ligne n'a pas d'effet. – Ian

6

Vous avez se rappeler que HEAD n'est qu'une suggestion au serveur web. Pour HEAD faire la bonne chose, il faut souvent un effort explicite de la part des administrateurs. Si vous avez un fichier statique Apache (ou quel que soit votre serveur web), vous devrez souvent faire le bon choix. Si vous dirigez une page dynamique, la valeur par défaut pour la plupart des configurations est d'exécuter le chemin GET, de collecter tous les résultats et de renvoyer les en-têtes sans le contenu.Si cette application est dans une configuration à trois niveaux (ou plus), cet appel pourrait être très coûteux et inutile pour un contexte HEAD. Par exemple, sur une servlet Java, par défaut, doHead() n'appelle que doGet(). Pour faire quelque chose d'un peu plus intelligent pour l'application, le développeur devrait implémenter explicitement doHead() (et le plus souvent, ce ne sera pas le cas).

J'ai rencontré une application d'une société de fortune 100 qui est utilisée pour télécharger plusieurs centaines de mégaoctets d'informations sur les prix. Nous vérifions les mises à jour de ces données en exécutant des requêtes HEAD assez régulièrement jusqu'à ce que la date de modification ait changé. Il s'avère que cette requête ferait en réalité des appels back end pour générer cette liste chaque fois que nous ferions la requête qui impliquait des gigaoctets de données sur leur back-end et les ferions passer entre plusieurs serveurs internes. Ils n'étaient pas très heureux avec nous, mais une fois que nous avons expliqué le cas d'utilisation, ils ont rapidement trouvé une solution alternative. S'ils avaient implémenté HEAD, plutôt que de se fier à leur serveur web pour le truquer, cela n'aurait pas été un problème.

0

Ce:

curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); 

Je ne cherche pas à obtenir les en-têtes.
J'essayais juste de faire en sorte que le chargement de certaines données ne prenne pas 2 minutes comme décrit ci-dessus.
Ce petit nombre d'options magiques est tombé à 2 secondes.

3

J'ai utilisé la fonction ci-dessous pour trouver l'URL redirigée.

$head = get_headers($url, 1); 

Le deuxième argument le fait retourner un tableau avec des clés. Par exemple le ci-dessous donnera la valeur Location.

$head["Location"] 

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

+1

Notez que bien que cette fonction utilise une requête GET par défaut, vous pouvez l'utiliser pour utiliser une requête HEAD (pour réduire le temps système en ne récupérant pas une page entière, le cas échéant) avec les fonctions stream_context de PHP. Un exemple est fourni dans l'entrée manuelle. – Synexis

Questions connexes