Comment puis-je vérifier si une URL existe via PHP?

Réponses:

297

Ici:

$file = 'http://www.domain.com/somefile.jpg';
$file_headers = @get_headers($file);
if(!$file_headers || $file_headers[0] == 'HTTP/1.1 404 Not Found') {
    $exists = false;
}
else {
    $exists = true;
}

À partir d' ici et juste en dessous du post ci -dessus, il existe une solution curl :

function url_exists($url) {
    if (!$fp = curl_init($url)) return false;
    return true;
}
karim79
la source
18
J'ai peur que la méthode CURL ne fonctionne pas de cette façon. Vérifiez ceci: stackoverflow.com/questions/981954/…
viam0Zah
4
certains sites Web ont une $file_headers[0]page d'erreur différente . par exemple, youtube.com. sa page d'erreur ayant cette valeur comme HTTP/1.0 404 Not Found(la différence est 1,0 et 1,1). que faire alors?
Krishna Raj K
21
Peut-être que l'utilisation strpos($headers[0], '404 Not Found')pourrait faire l'affaire
alexandru.topliceanu
12
@Mark est d'accord! Pour clarifier, strpos($headers[0], '404')c'est mieux!
alexandru.topliceanu
1
@ karim79 attention aux attaques SSRF et XSPA
M Rostami
55

Lorsque vous déterminez si une URL existe depuis php, il y a quelques points à prendre en compte:

  • Est-ce que l'url elle-même est valide (une chaîne, pas vide, bonne syntaxe), c'est rapide à vérifier côté serveur.
  • Attendre une réponse peut prendre du temps et bloquer l'exécution du code.
  • Tous les en-têtes renvoyés par get_headers () ne sont pas bien formés.
  • Utilisez curl (si vous le pouvez).
  • Empêchez de récupérer tout le corps / contenu, mais ne demandez que les en-têtes.
  • Pensez à rediriger les URL:
    • Voulez-vous que le premier code soit renvoyé?
    • Ou suivre toutes les redirections et renvoyer le dernier code?
    • Vous pourriez vous retrouver avec un 200, mais il pourrait rediriger à l'aide de balises méta ou de javascript. Il est difficile de comprendre ce qui se passe après.

Gardez à l'esprit que quelle que soit la méthode que vous utilisez, il faut du temps pour attendre une réponse.
Tout le code peut (et le fera probablement) s'arrêter jusqu'à ce que vous connaissiez le résultat ou que les requêtes aient expiré.

Par exemple: le code ci-dessous peut mettre LONGTEMPS à afficher la page si les URL sont invalides ou inaccessibles:

<?php
$urls = getUrls(); // some function getting say 10 or more external links

foreach($urls as $k=>$url){
  // this could potentially take 0-30 seconds each
  // (more or less depending on connection, target site, timeout settings...)
  if( ! isValidUrl($url) ){
    unset($urls[$k]);
  }
}

echo "yay all done! now show my site";
foreach($urls as $url){
  echo "<a href=\"{$url}\">{$url}</a><br/>";
}

Les fonctions ci-dessous pourraient être utiles, vous souhaiterez probablement les modifier en fonction de vos besoins:

    function isValidUrl($url){
        // first do some quick sanity checks:
        if(!$url || !is_string($url)){
            return false;
        }
        // quick check url is roughly a valid http request: ( http://blah/... ) 
        if( ! preg_match('/^http(s)?:\/\/[a-z0-9-]+(\.[a-z0-9-]+)*(:[0-9]+)?(\/.*)?$/i', $url) ){
            return false;
        }
        // the next bit could be slow:
        if(getHttpResponseCode_using_curl($url) != 200){
//      if(getHttpResponseCode_using_getheaders($url) != 200){  // use this one if you cant use curl
            return false;
        }
        // all good!
        return true;
    }

    function getHttpResponseCode_using_curl($url, $followredirects = true){
        // returns int responsecode, or false (if url does not exist or connection timeout occurs)
        // NOTE: could potentially take up to 0-30 seconds , blocking further code execution (more or less depending on connection, target site, and local timeout settings))
        // if $followredirects == false: return the FIRST known httpcode (ignore redirects)
        // if $followredirects == true : return the LAST  known httpcode (when redirected)
        if(! $url || ! is_string($url)){
            return false;
        }
        $ch = @curl_init($url);
        if($ch === false){
            return false;
        }
        @curl_setopt($ch, CURLOPT_HEADER         ,true);    // we want headers
        @curl_setopt($ch, CURLOPT_NOBODY         ,true);    // dont need body
        @curl_setopt($ch, CURLOPT_RETURNTRANSFER ,true);    // catch output (do NOT print!)
        if($followredirects){
            @curl_setopt($ch, CURLOPT_FOLLOWLOCATION ,true);
            @curl_setopt($ch, CURLOPT_MAXREDIRS      ,10);  // fairly random number, but could prevent unwanted endless redirects with followlocation=true
        }else{
            @curl_setopt($ch, CURLOPT_FOLLOWLOCATION ,false);
        }
//      @curl_setopt($ch, CURLOPT_CONNECTTIMEOUT ,5);   // fairly random number (seconds)... but could prevent waiting forever to get a result
//      @curl_setopt($ch, CURLOPT_TIMEOUT        ,6);   // fairly random number (seconds)... but could prevent waiting forever to get a result
//      @curl_setopt($ch, CURLOPT_USERAGENT      ,"Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1");   // pretend we're a regular browser
        @curl_exec($ch);
        if(@curl_errno($ch)){   // should be 0
            @curl_close($ch);
            return false;
        }
        $code = @curl_getinfo($ch, CURLINFO_HTTP_CODE); // note: php.net documentation shows this returns a string, but really it returns an int
        @curl_close($ch);
        return $code;
    }

    function getHttpResponseCode_using_getheaders($url, $followredirects = true){
        // returns string responsecode, or false if no responsecode found in headers (or url does not exist)
        // NOTE: could potentially take up to 0-30 seconds , blocking further code execution (more or less depending on connection, target site, and local timeout settings))
        // if $followredirects == false: return the FIRST known httpcode (ignore redirects)
        // if $followredirects == true : return the LAST  known httpcode (when redirected)
        if(! $url || ! is_string($url)){
            return false;
        }
        $headers = @get_headers($url);
        if($headers && is_array($headers)){
            if($followredirects){
                // we want the the last errorcode, reverse array so we start at the end:
                $headers = array_reverse($headers);
            }
            foreach($headers as $hline){
                // search for things like "HTTP/1.1 200 OK" , "HTTP/1.0 200 OK" , "HTTP/1.1 301 PERMANENTLY MOVED" , "HTTP/1.1 400 Not Found" , etc.
                // note that the exact syntax/version/output differs, so there is some string magic involved here
                if(preg_match('/^HTTP\/\S+\s+([1-9][0-9][0-9])\s+.*/', $hline, $matches) ){// "HTTP/*** ### ***"
                    $code = $matches[1];
                    return $code;
                }
            }
            // no HTTP/xxx found in headers:
            return false;
        }
        // no headers :
        return false;
    }
MoonLite
la source
pour une raison quelconque, getHttpResponseCode_using_curl () renvoie toujours 200 dans mon cas.
TD_Nijboer
2
si quelqu'un a le même problème, vérifiez dns-nameservers .. utilisez des opendns sans followredirects stackoverflow.com/a/11072947/1829460
TD_Nijboer
+1 pour être la seule réponse pour traiter les redirections. Changé le return $codepour if($code == 200){return true;} return false;trier uniquement les succès
Birrel
@PKHunter: Non. Mon expression régulière preg_match rapide était un exemple simple et ne correspondra pas à toutes les URL listées ici. Voir cette url de test: regex101.com/r/EpyDDc/2 Si vous en voulez une meilleure, remplacez-la par celle répertoriée sur votre lien ( mathiasbynens.be/demo/url-regex ) de diegoperini; il semble correspondre à tous, voir ce lien de test: regex101.com/r/qMQp23/1
MoonLite
46
$headers = @get_headers($this->_value);
if(strpos($headers[0],'200')===false)return false;

donc chaque fois que vous contactez un site Web et obtenez autre chose que 200 ok, cela fonctionnera

lunarnet76
la source
13
Mais que faire si c'est une redirection? Le domaine est toujours valide, mais sera laissé de côté.
Eric Leroy
4
Au- dessus sur une seule ligne: return strpos(@get_headers($url)[0],'200') === false ? false : true. Cela pourrait être utile.
Dejv
$ this is in PHP est une référence à l'objet courant. Référence: php.net/manual/en/language.oop5.basic.php Primer: phpro.org/tutorials/Object-Oriented-Programming-with-PHP.html L' extrait de code a probablement été extrait d'une classe et n'a pas été corrigé en conséquence .
Marc Witteveen
18

vous ne pouvez pas utiliser curl sur certains serveurs vous pouvez utiliser ce code

<?php
$url = 'http://www.example.com';
$array = get_headers($url);
$string = $array[0];
if(strpos($string,"200"))
  {
    echo 'url exists';
  }
  else
  {
    echo 'url does not exist';
  }
?>
Minhaz
la source
cela peut ne pas fonctionner pour la redirection 302-303 ou par exemple 304 Not Modified
Zippp
8
$url = 'http://google.com';
$not_url = 'stp://google.com';

if (@file_get_contents($url)): echo "Found '$url'!";
else: echo "Can't find '$url'.";
endif;
if (@file_get_contents($not_url)): echo "Found '$not_url!";
else: echo "Can't find '$not_url'.";
endif;

// Found 'http://google.com'!Can't find 'stp://google.com'.
Randy Skretka
la source
2
Cela ne fonctionnera pas si allow-url-fopen est désactivé. - php.net/manual/en/…
Daniel Paul Searles
2
Je suggérerais de ne lire que le premier octet ... if (@file_get_contents ($ url, false, NULL, 0,1))
Daniel Valland
8
function URLIsValid($URL)
{
    $exists = true;
    $file_headers = @get_headers($URL);
    $InvalidHeaders = array('404', '403', '500');
    foreach($InvalidHeaders as $HeaderVal)
    {
            if(strstr($file_headers[0], $HeaderVal))
            {
                    $exists = false;
                    break;
            }
    }
    return $exists;
}
Leela
la source
8

J'utilise cette fonction:

/**
 * @param $url
 * @param array $options
 * @return string
 * @throws Exception
 */
function checkURL($url, array $options = array()) {
    if (empty($url)) {
        throw new Exception('URL is empty');
    }

    // list of HTTP status codes
    $httpStatusCodes = array(
        100 => 'Continue',
        101 => 'Switching Protocols',
        102 => 'Processing',
        200 => 'OK',
        201 => 'Created',
        202 => 'Accepted',
        203 => 'Non-Authoritative Information',
        204 => 'No Content',
        205 => 'Reset Content',
        206 => 'Partial Content',
        207 => 'Multi-Status',
        208 => 'Already Reported',
        226 => 'IM Used',
        300 => 'Multiple Choices',
        301 => 'Moved Permanently',
        302 => 'Found',
        303 => 'See Other',
        304 => 'Not Modified',
        305 => 'Use Proxy',
        306 => 'Switch Proxy',
        307 => 'Temporary Redirect',
        308 => 'Permanent Redirect',
        400 => 'Bad Request',
        401 => 'Unauthorized',
        402 => 'Payment Required',
        403 => 'Forbidden',
        404 => 'Not Found',
        405 => 'Method Not Allowed',
        406 => 'Not Acceptable',
        407 => 'Proxy Authentication Required',
        408 => 'Request Timeout',
        409 => 'Conflict',
        410 => 'Gone',
        411 => 'Length Required',
        412 => 'Precondition Failed',
        413 => 'Payload Too Large',
        414 => 'Request-URI Too Long',
        415 => 'Unsupported Media Type',
        416 => 'Requested Range Not Satisfiable',
        417 => 'Expectation Failed',
        418 => 'I\'m a teapot',
        422 => 'Unprocessable Entity',
        423 => 'Locked',
        424 => 'Failed Dependency',
        425 => 'Unordered Collection',
        426 => 'Upgrade Required',
        428 => 'Precondition Required',
        429 => 'Too Many Requests',
        431 => 'Request Header Fields Too Large',
        449 => 'Retry With',
        450 => 'Blocked by Windows Parental Controls',
        500 => 'Internal Server Error',
        501 => 'Not Implemented',
        502 => 'Bad Gateway',
        503 => 'Service Unavailable',
        504 => 'Gateway Timeout',
        505 => 'HTTP Version Not Supported',
        506 => 'Variant Also Negotiates',
        507 => 'Insufficient Storage',
        508 => 'Loop Detected',
        509 => 'Bandwidth Limit Exceeded',
        510 => 'Not Extended',
        511 => 'Network Authentication Required',
        599 => 'Network Connect Timeout Error'
    );

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_NOBODY, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

    if (isset($options['timeout'])) {
        $timeout = (int) $options['timeout'];
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
    }

    curl_exec($ch);
    $returnedStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if (array_key_exists($returnedStatusCode, $httpStatusCodes)) {
        return "URL: '{$url}' - Error code: {$returnedStatusCode} - Definition: {$httpStatusCodes[$returnedStatusCode]}";
    } else {
        return "'{$url}' does not exist";
    }
}
Ehsan
la source
5

La solution get_headers () de karim79 n'a pas fonctionné pour moi car j'ai obtenu des résultats fous avec Pinterest.

get_headers(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

Array
(
    [url] => https://www.pinterest.com/jonathan_parl/
    [exists] => 
)

get_headers(): Failed to enable crypto

Array
(
    [url] => https://www.pinterest.com/jonathan_parl/
    [exists] => 
)

get_headers(https://www.pinterest.com/jonathan_parl/): failed to open stream: operation failed

Array
(
    [url] => https://www.pinterest.com/jonathan_parl/
    [exists] => 
) 

Quoi qu'il en soit, ce développeur démontre que cURL est bien plus rapide que get_headers ():

http://php.net/manual/fr/function.get-headers.php#104723

Étant donné que de nombreuses personnes ont demandé que karim79 répare sa solution cURL, voici la solution que j'ai construite aujourd'hui.

/**
* Send an HTTP request to a the $url and check the header posted back.
*
* @param $url String url to which we must send the request.
* @param $failCodeList Int array list of code for which the page is considered invalid.
*
* @return Boolean
*/
public static function isUrlExists($url, array $failCodeList = array(404)){

    $exists = false;

    if(!StringManager::stringStartWith($url, "http") and !StringManager::stringStartWith($url, "ftp")){

        $url = "https://" . $url;
    }

    if (preg_match(RegularExpression::URL, $url)){

        $handle = curl_init($url);


        curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);

        curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);

        curl_setopt($handle, CURLOPT_HEADER, true);

        curl_setopt($handle, CURLOPT_NOBODY, true);

        curl_setopt($handle, CURLOPT_USERAGENT, true);


        $headers = curl_exec($handle);

        curl_close($handle);


        if (empty($failCodeList) or !is_array($failCodeList)){

            $failCodeList = array(404); 
        }

        if (!empty($headers)){

            $exists = true;

            $headers = explode(PHP_EOL, $headers);

            foreach($failCodeList as $code){

                if (is_numeric($code) and strpos($headers[0], strval($code)) !== false){

                    $exists = false;

                    break;  
                }
            }
        }
    }

    return $exists;
}

Laissez-moi vous expliquer les options de curl:

CURLOPT_RETURNTRANSFER : renvoie une chaîne au lieu d'afficher la page appelante à l'écran.

CURLOPT_SSL_VERIFYPEER : cUrl ne récupérera pas le certificat

CURLOPT_HEADER : inclure l'en-tête dans la chaîne

CURLOPT_NOBODY : ne pas inclure le corps dans la chaîne

CURLOPT_USERAGENT : certains sites en ont besoin pour fonctionner correctement (par exemple: https://plus.google.com )


Note supplémentaire : Dans cette fonction, j'utilise l'expression régulière de Diego Perini pour valider l'URL avant d'envoyer la requête:

const URL = "%^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@|\d{1,3}(?:\.\d{1,3}){3}|(?:(?:[a-z\d\x{00a1}-\x{ffff}]+-?)*[a-z\d\x{00a1}-\x{ffff}]+)(?:\.(?:[a-z\d\x{00a1}-\x{ffff}]+-?)*[a-z\d\x{00a1}-\x{ffff}]+)*(?:\.[a-z\x{00a1}-\x{ffff}]{2,6}))(?::\d+)?(?:[^\s]*)?$%iu"; //@copyright Diego Perini

Note complémentaire 2 : j'explose la chaîne d'en-tête et les en-têtes utilisateur [0] pour être sûr de ne valider que le code retour et le message (exemple: 200, 404, 405, etc.)

Note supplémentaire 3 : Parfois, valider uniquement le code 404 ne suffit pas (voir le test unitaire), il existe donc un paramètre facultatif $ failCodeList pour fournir toute la liste de codes à rejeter.

Et, bien sûr, voici le test unitaire (y compris tout le réseau social populaire) pour légitimer mon codage:

public function testIsUrlExists(){

//invalid
$this->assertFalse(ToolManager::isUrlExists("woot"));

$this->assertFalse(ToolManager::isUrlExists("https://www.facebook.com/jonathan.parentlevesque4545646456"));

$this->assertFalse(ToolManager::isUrlExists("https://plus.google.com/+JonathanParentL%C3%A9vesque890800"));

$this->assertFalse(ToolManager::isUrlExists("https://instagram.com/mariloubiz1232132/", array(404, 405)));

$this->assertFalse(ToolManager::isUrlExists("https://www.pinterest.com/jonathan_parl1231/"));

$this->assertFalse(ToolManager::isUrlExists("https://regex101.com/546465465456"));

$this->assertFalse(ToolManager::isUrlExists("https://twitter.com/arcadefire4566546"));

$this->assertFalse(ToolManager::isUrlExists("https://vimeo.com/**($%?%$", array(400, 405)));

$this->assertFalse(ToolManager::isUrlExists("https://www.youtube.com/user/Darkjo666456456456"));


//valid
$this->assertTrue(ToolManager::isUrlExists("www.google.ca"));

$this->assertTrue(ToolManager::isUrlExists("https://www.facebook.com/jonathan.parentlevesque"));

$this->assertTrue(ToolManager::isUrlExists("https://plus.google.com/+JonathanParentL%C3%A9vesque"));

$this->assertTrue(ToolManager::isUrlExists("https://instagram.com/mariloubiz/"));

$this->assertTrue(ToolManager::isUrlExists("https://www.facebook.com/jonathan.parentlevesque"));

$this->assertTrue(ToolManager::isUrlExists("https://www.pinterest.com/"));

$this->assertTrue(ToolManager::isUrlExists("https://regex101.com"));

$this->assertTrue(ToolManager::isUrlExists("https://twitter.com/arcadefire"));

$this->assertTrue(ToolManager::isUrlExists("https://vimeo.com/"));

$this->assertTrue(ToolManager::isUrlExists("https://www.youtube.com/user/Darkjo666"));
}

Grand succès à tous,

Jonathan Parent-Lévesque de Montréal

Jonathan Parent Lévesque
la source
4
function urlIsOk($url)
{
    $headers = @get_headers($url);
    $httpStatus = intval(substr($headers[0], 9, 3));
    if ($httpStatus<400)
    {
        return true;
    }
    return false;
}
Spir
la source
3

assez vite:

function http_response($url){
    $resURL = curl_init(); 
    curl_setopt($resURL, CURLOPT_URL, $url); 
    curl_setopt($resURL, CURLOPT_BINARYTRANSFER, 1); 
    curl_setopt($resURL, CURLOPT_HEADERFUNCTION, 'curlHeaderCallback'); 
    curl_setopt($resURL, CURLOPT_FAILONERROR, 1); 
    curl_exec ($resURL); 
    $intReturnCode = curl_getinfo($resURL, CURLINFO_HTTP_CODE); 
    curl_close ($resURL); 
    if ($intReturnCode != 200 && $intReturnCode != 302 && $intReturnCode != 304) { return 0; } else return 1;
}

echo 'google:';
echo http_response('http://www.google.com');
echo '/ ogogle:';
echo http_response('http://www.ogogle.com');
Sebastian Lasse
la source
Trop compliqué :) stackoverflow.com/questions/981954/…
Ja͢ck
J'obtiens
3

Toutes les solutions ci-dessus + sucre supplémentaire. (Solution AIO ultime)

/**
 * Check that given URL is valid and exists.
 * @param string $url URL to check
 * @return bool TRUE when valid | FALSE anyway
 */
function urlExists ( $url ) {
    // Remove all illegal characters from a url
    $url = filter_var($url, FILTER_SANITIZE_URL);

    // Validate URI
    if (filter_var($url, FILTER_VALIDATE_URL) === FALSE
        // check only for http/https schemes.
        || !in_array(strtolower(parse_url($url, PHP_URL_SCHEME)), ['http','https'], true )
    ) {
        return false;
    }

    // Check that URL exists
    $file_headers = @get_headers($url);
    return !(!$file_headers || $file_headers[0] === 'HTTP/1.1 404 Not Found');
}

Exemple:

var_dump ( urlExists('http://stackoverflow.com/') );
// Output: true;
Junaid Atari
la source
3

pour vérifier si l'URL est en ligne ou hors ligne ---

function get_http_response_code($theURL) {
    $headers = @get_headers($theURL);
    return substr($headers[0], 9, 3);
}
Hosam Elzagh
la source
3
function url_exists($url) {
    $headers = @get_headers($url);
    return (strpos($headers[0],'200')===false)? false:true;
}
Krishna Guragai
la source
2

Voici une solution qui ne lit que le premier octet du code source ... renvoyant false si le file_get_contents échoue ... Cela fonctionnera également pour les fichiers distants comme les images.

 function urlExists($url)
{
    if (@file_get_contents($url,false,NULL,0,1))
    {
        return true;
    }
    return false;
}
Daniel Valland
la source
0

la manière simple est de boucler (et plus rapide aussi)

<?php
$mylinks="http://site.com/page.html";
$handlerr = curl_init($mylinks);
curl_setopt($handlerr,  CURLOPT_RETURNTRANSFER, TRUE);
$resp = curl_exec($handlerr);
$ht = curl_getinfo($handlerr, CURLINFO_HTTP_CODE);


if ($ht == '404')
     { echo 'OK';}
else { echo 'NO';}

?>
T.Todua
la source
0

Une autre façon de vérifier si une URL est valide ou non peut être:

<?php

  if (isValidURL("http://www.gimepix.com")) {
      echo "URL is valid...";
  } else {
      echo "URL is not valid...";
  }

  function isValidURL($url) {
      $file_headers = @get_headers($url);
      if (strpos($file_headers[0], "200 OK") > 0) {
         return true;
      } else {
        return false;
      }
  }
?>
Antonio Carlos Barbosa
la source
0

get_headers () retourne un tableau avec les en-têtes envoyés par le serveur en réponse à une requête HTTP.

$image_path = 'https://your-domain.com/assets/img/image.jpg';

$file_headers = @get_headers($image_path);
//Prints the response out in an array
//print_r($file_headers); 

if($file_headers[0] == 'HTTP/1.1 404 Not Found'){
   echo 'Failed because path does not exist.</br>';
}else{
   echo 'It works. Your good to go!</br>';
}
Jeacovy Gayle
la source
0

cURL peut renvoyer du code HTTP Je ne pense pas que tout ce code supplémentaire soit nécessaire?

function urlExists($url=NULL)
    {
        if($url == NULL) return false;
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $data = curl_exec($ch);
        $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch); 
        if($httpcode>=200 && $httpcode<300){
            return true;
        } else {
            return false;
        }
    }
Arun Vitto
la source
0

Une chose à prendre en compte lorsque vous vérifiez l'en-tête d'un 404 est le cas où un site ne génère pas immédiatement un 404.

De nombreux sites vérifient si une page existe ou non dans la source PHP / ASP (et cetera) et vous redirigent vers une page 404. Dans ces cas, l'en-tête est essentiellement étendu par l'en-tête du 404 qui est généré. Dans ces cas, l'erreur 404 n'est pas dans la première ligne de l'en-tête, mais dans la dixième.

$array = get_headers($url);
$string = $array[0];
print_r($string) // would generate:

Array ( 
[0] => HTTP/1.0 301 Moved Permanently 
[1] => Date: Fri, 09 Nov 2018 16:12:29 GMT 
[2] => Server: Apache/2.4.34 (FreeBSD) LibreSSL/2.7.4 PHP/7.0.31 
[3] => X-Powered-By: PHP/7.0.31 
[4] => Set-Cookie: landing=%2Freed-diffuser-fig-pudding-50; path=/; HttpOnly 
[5] => Location: /reed-diffuser-fig-pudding-50/ 
[6] => Content-Length: 0 
[7] => Connection: close 
[8] => Content-Type: text/html; charset=utf-8 
[9] => HTTP/1.0 404 Not Found 
[10] => Date: Fri, 09 Nov 2018 16:12:29 GMT 
[11] => Server: Apache/2.4.34 (FreeBSD) LibreSSL/2.7.4 PHP/7.0.31 
[12] => X-Powered-By: PHP/7.0.31 
[13] => Set-Cookie: landing=%2Freed-diffuser-fig-pudding-50%2F; path=/; HttpOnly 
[14] => Connection: close 
[15] => Content-Type: text/html; charset=utf-8 
) 
Lexib0y
la source
0

J'exécute des tests pour voir si les liens sur mon site sont valides - m'alerte lorsque des tiers modifient leurs liens. J'avais un problème avec un site qui avait un certificat mal configuré qui signifiait que les get_headers de php ne fonctionnaient pas.

Donc, j'ai lu que curl était plus rapide et j'ai décidé de l'essayer. puis j'ai eu un problème avec linkedin qui m'a donné une erreur 999, qui s'est avérée être un problème d'agent utilisateur.

Je m'en fichais si le certificat n'était pas valide pour ce test, et je m'en fichais si la réponse était une redirection.

Ensuite, j'ai pensé utiliser get_headers de toute façon si curl échouait ...

Essayez....

/**
 * returns true/false if the $url is present.
 *
 * @param string $url assumes this is a valid url.
 *
 * @return bool
 */
private function url_exists (string $url): bool
{
  $ch = curl_init($url);
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_NOBODY, TRUE);             // this does a head request to make it faster.
  curl_setopt($ch, CURLOPT_HEADER, TRUE);             // just the headers
  curl_setopt($ch, CURLOPT_SSL_VERIFYSTATUS, FALSE);  // turn off that pesky ssl stuff - some sys admins can't get it right.
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  // set a real user agent to stop linkedin getting upset.
  curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36');
  curl_exec($ch);
  $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  if (($http_code >= HTTP_OK && $http_code < HTTP_BAD_REQUEST) || $http_code === 999)
  {
    curl_close($ch);
    return TRUE;
  }
  $error = curl_error($ch); // used for debugging.
  curl_close($ch);
  // just try the get_headers - it might work!
  stream_context_set_default(array('http' => array('method' => 'HEAD')));
  $file_headers = @get_headers($url);
  if ($file_headers)
  {
    $response_code = substr($file_headers[0], 9, 3);
    return $response_code >= 200 && $response_code < 400;
  }
  return FALSE;
}
pgee70
la source
-2

sorte d'un vieux fil, mais .. je fais ceci:

$file = 'http://www.google.com';
$file_headers = @get_headers($file);
if ($file_headers) {
    $exists = true;
} else {
    $exists = false;
}
hackdotslashdotkill
la source
Sorta .. Mais pas exactement.
hackdotslashdotkill
comment votre réponse est-elle meilleure?
Jah
@Jah c'est évidemment pas c'est à -2. J'ai probablement posté ça tard dans la nuit alors que j'étais à moitié endormi après avoir regardé des écrans toute la journée ..
hackdotslashdotkill