2009-04-20 9 views
21

Ho un codice semplice che esegue una richiesta di testa per un URL e quindi stampa le intestazioni di risposta. Ho notato che su alcuni siti, questo può richiedere molto tempo per essere completato.PHP/Curl: la richiesta HEAD richiede molto tempo su alcuni siti

Ad esempio, la richiesta di http://www.arstechnica.com richiede circa due minuti. Ho provato la stessa richiesta utilizzando un altro sito web che svolge la stessa attività di base e torna immediatamente. Quindi ci deve essere qualcosa che ho impostato in modo errato che sta causando questo ritardo.

Ecco il codice che ho:

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

Ecco un link al sito web che fa la stessa funzione: http://www.seoconsultants.com/tools/headers.asp

Il codice di cui sopra, almeno sul mio server, richiede due minuti per recuperare www.arstechnica.com, ma il servizio al link qui sopra lo restituisce immediatamente.

Cosa mi manca?

+1

quello _curl_ che manca è un corpo di risposta, che non sa che le richieste HEAD restituiscono solo le intestazioni (senza corpo) in modo che sia in attesa per il server di inviare ulteriori dati. così arricciato aspetta per 2 minuti e poi si arrende. – Jasen

risposta

41

provare a semplificare un po ':

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

Le uscite di cui sopra immediatamente sul mio webserver. Se non è sul tuo, c'è una buona probabilità che il tuo host web abbia qualche tipo di impostazione per limitare questo tipo di richieste.

EDIT:

Dato quanto sopra avviene istantaneamente per voi, provate ad impostare this curl setting sul codice originale:

curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, true); 

Utilizzando lo strumento che hai postato, ho notato che http://www.arstechnica.com ha un 301 intestazione inviato per qualsiasi richiesta inviata ad esso. È possibile che cURL stia ricevendo questo e non seguendo la nuova posizione specificata, causando così il blocco dello script.

SECONDO EDIT:

Curiosamente, provando lo stesso codice che avete sopra stava facendo mio webserver appendere troppo. Ho sostituito questo codice:

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

Con questo:

curl_setopt($ch, CURLOPT_NOBODY, true); 

Qual è il modo the manual raccomanda di fare una richiesta HEAD. Ha funzionato all'istante.

+0

che emette istantaneamente il codice html di www.arstechnica.com. – Ian

+0

nessun cambiamento, sfortunatamente. – Ian

+0

e sto cercando di recuperare solo le intestazioni di risposta della prima pagina, e non più avanti sulla linea. – Ian

2

Se la memoria non riesce a me fare una richiesta HEAD nel CURL cambia la versione del protocollo HTTP a 1.0 (che è lento e probabilmente la parte colpevole qui) provare a cambiare quello 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); 
+0

sembra utilizzare HTTP 1.1 per impostazione predefinita, almeno in base alla risposta che ottengo alla fine: HTTP/1.1 301 spostato in modo permanente in ogni caso, l'aggiunta di quella linea non ha alcun effetto. – Ian

6

Hai per ricordare che HEAD è solo un suggerimento per il web server. Per HEAD fare la cosa giusta spesso ci vuole uno sforzo esplicito da parte degli amministratori. Se esegui un file statico Apache (o qualsiasi cosa sia il tuo server web), spesso eseguirai una cosa giusta. Se SENTIRE una pagina dinamica, il valore predefinito per la maggior parte delle impostazioni è eseguire il percorso GET, raccogliere tutti i risultati e semplicemente inviare indietro le intestazioni senza il contenuto.Se tale applicazione si trova in una configurazione a 3 (o più) livelli, quella chiamata potrebbe essere potenzialmente molto costosa e inutile per un contesto HEAD. Ad esempio, su un servlet Java, per impostazione predefinita doHead() chiama semplicemente doGet(). Per fare qualcosa di un po 'più intelligente per l'applicazione, lo sviluppatore dovrebbe implementare esplicitamente doHead() (e più spesso che no, non lo farà).

Ho trovato un'app da un'azienda Fortune 100 che viene utilizzata per scaricare diverse centinaia di megabyte di informazioni sui prezzi. Controlleremmo gli aggiornamenti di tali dati eseguendo le richieste HEAD abbastanza regolarmente fino a quando la data di modifica non fosse stata modificata. Si scopre che questa richiesta in realtà farebbe chiamate di back-end per generare questo elenco ogni volta che abbiamo fatto la richiesta che comportava gigabyte di dati sul loro back-end e lo differiva tra diversi server interni. Non erano molto felici con noi, ma una volta che abbiamo spiegato il caso d'uso hanno trovato rapidamente una soluzione alternativa. Se avessero implementato HEAD, anziché affidarsi al proprio server Web per simularlo, non sarebbe stato un problema.

0

questo:

curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); 

Non stavo cercando di ottenere le intestazioni.
Stavo solo cercando di rendere il caricamento della pagina di alcuni dati non più di 2 minuti come descritto sopra.
Quelle piccole e magiche opzioni l'hanno ridotto a 2 secondi.

3

Ho usato la funzione qui sotto per trovare l'URL reindirizzato.

$head = get_headers($url, 1); 

Il secondo argomento consente di restituire un array con le chiavi. Ad es. il sotto fornirà il valore Location.

$head["Location"] 

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

+1

Si noti che mentre questa funzione utilizza una richiesta GET per impostazione predefinita, è possibile impostarla per utilizzare una richiesta HEAD (per ridurre il sovraccarico non recuperando un'intera pagina, se applicabile) con le funzioni stream_context di PHP. Un esempio è fornito nella voce di manuale. – Synexis

Problemi correlati