J'apprends moi-même quelques notions élémentaires et j'ai parfois constaté que les URL que je saisissais dans mon code retournent 404, ce qui gomme le reste de mon code.
J'ai donc besoin d'un test en haut du code pour vérifier si l'URL renvoie 404 ou non.
Cela semblerait être une tâche plutôt simple, mais Google ne me donne aucune réponse. Je m'inquiète de chercher le mauvais matériel.
Un blog m'a recommandé d'utiliser ceci:
$valid = @fsockopen($url, 80, $errno, $errstr, 30);
puis testez pour voir si $ valide s'il est vide ou non.
Mais je pense que l'URL qui me pose des problèmes contient une redirection, donc $ valid est à venir vide pour toutes les valeurs. Ou peut-être que je fais autre chose de mal.
J'ai également examiné une "requête principale", mais je n'ai pas encore trouvé d'exemples de code réels avec lesquels je peux jouer ou essayer.
Suggestions? Et qu'est-ce que c'est à propos de curl?
Si vous utilisez PHP curl
bindings , vous pouvez vérifier le code d'erreur en utilisant curl_getinfo
en tant que tel:
_$handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE);
/* Get the HTML or whatever is linked in $url. */
$response = curl_exec($handle);
/* Check for 404 (file not found). */
$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
if($httpCode == 404) {
/* Handle 404 here. */
}
curl_close($handle);
/* Handle $response here. */
_
Si vous utilisez php5, vous pouvez utiliser:
$url = 'http://www.example.com';
print_r(get_headers($url, 1));
Alternativement avec php4, un utilisateur a contribué à:
/**
This is a modified version of code from "stuart at sixletterwords dot com", at 14-Sep-2005 04:52. This version tries to emulate get_headers() function at PHP4. I think it works fairly well, and is simple. It is not the best emulation available, but it works.
Features:
- supports (and requires) full URLs.
- supports changing of default port in URL.
- stops downloading from socket as soon as end-of-headers is detected.
Limitations:
- only gets the root URL (see line with "GET / HTTP/1.1").
- don't support HTTPS (nor the default HTTPS port).
*/
if(!function_exists('get_headers'))
{
function get_headers($url,$format=0)
{
$url=parse_url($url);
$end = "\r\n\r\n";
$fp = fsockopen($url['Host'], (empty($url['port'])?80:$url['port']), $errno, $errstr, 30);
if ($fp)
{
$out = "GET / HTTP/1.1\r\n";
$out .= "Host: ".$url['Host']."\r\n";
$out .= "Connection: Close\r\n\r\n";
$var = '';
fwrite($fp, $out);
while (!feof($fp))
{
$var.=fgets($fp, 1280);
if(strpos($var,$end))
break;
}
fclose($fp);
$var=preg_replace("/\r\n\r\n.*\$/",'',$var);
$var=explode("\r\n",$var);
if($format)
{
foreach($var as $i)
{
if(preg_match('/^([a-zA-Z -]+): +(.*)$/',$i,$parts))
$v[$parts[1]]=$parts[2];
}
return $v;
}
else
return $var;
}
}
}
Les deux auraient un résultat similaire à:
Array
(
[0] => HTTP/1.1 200 OK
[Date] => Sat, 29 May 2004 12:28:14 GMT
[Server] => Apache/1.3.27 (Unix) (Red-Hat/Linux)
[Last-Modified] => Wed, 08 Jan 2003 23:11:55 GMT
[ETag] => "3f80f-1b6-3e1cb03b"
[Accept-Ranges] => bytes
[Content-Length] => 438
[Connection] => close
[Content-Type] => text/html
)
Par conséquent, vous pouvez simplement vérifier que la réponse de l'en-tête était OK, par exemple:
$headers = get_headers($url, 1);
if ($headers[0] == 'HTTP/1.1 200 OK') {
//valid
}
if ($headers[0] == 'HTTP/1.1 301 Moved Permanently') {
//moved or redirect page
}
Avec le code de strager, vous pouvez également vérifier le code CURLINFO_HTTP_CODE pour d’autres codes. Certains sites Web ne signalent pas un 404; ils redirigent simplement vers une page 404 personnalisée et renvoient 302 (redirection) ou quelque chose de similaire. J'ai utilisé cela pour vérifier si un fichier réel (par exemple, robots.txt) existait ou non sur le serveur. Clairement, ce type de fichier ne provoquerait pas de redirection s'il existait, mais s'il ne le faisait pas, il serait redirigé vers une page 404 qui, comme je l'ai dit précédemment, risque de ne pas contenir de code 404.
function is_404($url) {
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE);
/* Get the HTML or whatever is linked in $url. */
$response = curl_exec($handle);
/* Check for 404 (file not found). */
$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
/* If the document has loaded successfully without any redirection or error */
if ($httpCode >= 200 && $httpCode < 300) {
return false;
} else {
return true;
}
}
Comme suggéré par strager, envisagez d'utiliser cURL. Vous pouvez également être intéressé par la définition de CURLOPT_NOBODY avec curl_setopt pour ne pas télécharger la page entière (vous ne voulez que les en-têtes).
Si vous cherchez la solution la plus simple et celle que vous pouvez essayer en une fois sur php5 do
file_get_contents('www.yoursite.com');
//and check by echoing
echo $http_response_header[0];
J'ai trouvé cette réponse ici :
if(($Twitter_XML_raw=file_get_contents($timeline))==false){
// Retrieve HTTP status code
list($version,$status_code,$msg) = explode(' ',$http_response_header[0], 3);
// Check the HTTP Status code
switch($status_code) {
case 200:
$error_status="200: Success";
break;
case 401:
$error_status="401: Login failure. Try logging out and back in. Password are ONLY used when posting.";
break;
case 400:
$error_status="400: Invalid request. You may have exceeded your rate limit.";
break;
case 404:
$error_status="404: Not found. This shouldn't happen. Please let me know what happened using the feedback link above.";
break;
case 500:
$error_status="500: Twitter servers replied with an error. Hopefully they'll be OK soon!";
break;
case 502:
$error_status="502: Twitter servers may be down or being upgraded. Hopefully they'll be OK soon!";
break;
case 503:
$error_status="503: Twitter service unavailable. Hopefully they'll be OK soon!";
break;
default:
$error_status="Undocumented error: " . $status_code;
break;
}
Vous utilisez essentiellement la méthode "file get contents" pour récupérer l'URL, qui renseigne automatiquement la variable d'en-tête de réponse http avec le code d'état.
addendum; testé ces 3 méthodes en considérant les performances.
Le résultat, au moins dans mon environnement de test:
victoire gagne
Ce test est effectué en considérant que seuls les en-têtes (noBody) sont nécessaires. Testez-vous:
$url = "http://de.wikipedia.org/wiki/Pinocchio";
$start_time = microtime(TRUE);
$headers = get_headers($url);
echo $headers[0]."<br>";
$end_time = microtime(TRUE);
echo $end_time - $start_time."<br>";
$start_time = microtime(TRUE);
$response = file_get_contents($url);
echo $http_response_header[0]."<br>";
$end_time = microtime(TRUE);
echo $end_time - $start_time."<br>";
$start_time = microtime(TRUE);
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($handle, CURLOPT_NOBODY, 1); // and *only* get the header
/* Get the HTML or whatever is linked in $url. */
$response = curl_exec($handle);
/* Check for 404 (file not found). */
$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
// if($httpCode == 404) {
// /* Handle 404 here. */
// }
echo $httpCode."<br>";
curl_close($handle);
$end_time = microtime(TRUE);
echo $end_time - $start_time."<br>";
Cela vous donnera true si l'URL ne retourne pas 200 OK
function check_404($url) {
$headers=get_headers($url, 1);
if ($headers[0]!='HTTP/1.1 200 OK') return true; else return false;
}
En guise d’allusion supplémentaire à la grande réponse acceptée:
Lors de l'utilisation d'une variante de la solution proposée, j'ai eu des erreurs en raison du paramètre php 'max_execution_time'. Donc ce que j'ai fait était le suivant:
set_time_limit(120);
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_NOBODY, true);
$result = curl_exec($curl);
set_time_limit(ini_get('max_execution_time'));
curl_close($curl);
Tout d'abord, je règle la limite de temps sur un nombre de secondes plus élevé, puis je le redéfinis sur la valeur définie dans les paramètres php.
<?php
$url= 'www.something.com';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.4");
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_TIMEOUT,10);
curl_setopt($ch, CURLOPT_ENCODING, "gzip");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$output = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $httpcode;
?>
Vous pouvez aussi utiliser ce code pour voir le statut de n'importe quel lien:
<?php
function get_url_status($url, $timeout = 10)
{
$ch = curl_init();
// set cURL options
$opts = array(CURLOPT_RETURNTRANSFER => true, // do not output to browser
CURLOPT_URL => $url, // set URL
CURLOPT_NOBODY => true, // do a HEAD request only
CURLOPT_TIMEOUT => $timeout); // set timeout
curl_setopt_array($ch, $opts);
curl_exec($ch); // do it!
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE); // find HTTP status
curl_close($ch); // close handle
echo $status; //or return $status;
//example checking
if ($status == '302') { echo 'HEY, redirection';}
}
get_url_status('http://yourpage.comm');
?>
Voici une solution courte.
$handle = curl_init($uri);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($handle,CURLOPT_HTTPHEADER,array ("Accept: application/rdf+xml"));
curl_setopt($handle, CURLOPT_NOBODY, true);
curl_exec($handle);
$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
if($httpCode == 200||$httpCode == 303)
{
echo "you might get a reply";
}
curl_close($handle);
Dans votre cas, vous pouvez remplacer application/rdf+xml
par tout ce que vous utilisez.
c'est juste et tranche de code, l'espoir fonctionne pour vous
$ch = @curl_init();
@curl_setopt($ch, CURLOPT_URL, 'http://example.com');
@curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1");
@curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
@curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
@curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$response = @curl_exec($ch);
$errno = @curl_errno($ch);
$error = @curl_error($ch);
$response = $response;
$info = @curl_getinfo($ch);
return $info['http_code'];
Pour attraper toutes les erreurs: 4XX et 5XX, j'utilise ce petit script:
function URLIsValid($URL){
$headers = @get_headers($URL);
preg_match("/ [45][0-9]{2} /", (string)$headers[0] , $match);
return count($match) === 0;
}