Einige Websites haben eine andere $file_headers[0]Fehlerseite. Zum Beispiel youtube.com. Die Fehlerseite hat den Wert HTTP/1.0 404 Not Found(Differenz ist 1.0 und 1.1). was dann tun?
Krishna Raj K
21
Vielleicht strpos($headers[0], '404 Not Found')könnte die Verwendung den Trick tun
alexandru.topliceanu
12
@ Mark stimmte zu! Zu klären strpos($headers[0], '404')ist besser!
alexandru.topliceanu
1
@ Karim79 Vorsicht vor SSRF- und XSPA-Angriffen
M Rostami
55
Wenn Sie herausfinden möchten, ob eine URL von PHP existiert, sollten Sie einige Dinge beachten:
Ist die URL selbst gültig (eine Zeichenfolge, nicht leer, gute Syntax), kann die Serverseite schnell überprüft werden.
Das Warten auf eine Antwort kann einige Zeit dauern und die Codeausführung blockieren.
Nicht alle von get_headers () zurückgegebenen Header sind gut geformt.
Verwenden Sie Locken (wenn Sie können).
Verhindern Sie das Abrufen des gesamten Körpers / Inhalts, sondern fordern Sie nur die Header an.
Überlegen Sie, URLs umzuleiten:
Möchten Sie den ersten Code zurückgeben?
Oder folgen Sie allen Weiterleitungen und geben Sie den letzten Code zurück?
Möglicherweise erhalten Sie eine 200, die jedoch mithilfe von Meta-Tags oder Javascript umgeleitet wird. Herauszufinden, was danach passiert, ist schwierig.
Denken Sie daran, dass es einige Zeit dauert, auf eine Antwort zu warten, egal welche Methode Sie verwenden.
Der gesamte Code wird möglicherweise (und wird wahrscheinlich) angehalten, bis Sie entweder das Ergebnis kennen oder die Anforderungen abgelaufen sind.
Beispiel: Der folgende Code kann lange dauern, bis die Seite angezeigt wird, wenn die URLs ungültig oder nicht erreichbar sind:
<?php
$urls = getUrls();// some function getting say 10 or more external linksforeach($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/>";}
Die folgenden Funktionen könnten hilfreich sein. Sie möchten sie wahrscheinlich an Ihre Bedürfnisse anpassen:
function isValidUrl($url){// first do some quick sanity checks:if(!$url ||!is_string($url)){returnfalse;}// 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)){returnfalse;}// 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 curlreturnfalse;}// all good!returntrue;}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)){returnfalse;}
$ch =@curl_init($url);if($ch ===false){returnfalse;}@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);returnfalse;}
$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)){returnfalse;}
$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 hereif(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:returnfalse;}// no headers :returnfalse;}
Aus irgendeinem Grund gibt getHttpResponseCode_using_curl () in meinem Fall immer 200 zurück.
TD_Nijboer
2
Wenn jemand das gleiche Problem hat, überprüfen Sie DNS-Nameserver. Verwenden Sie opendns ohne followredirects stackoverflow.com/a/11072947/1829460
TD_Nijboer
+1 für die einzige Antwort, die sich mit Weiterleitungen befasst. Changed die return $codeauf if($code == 200){return true;} return false;nur aussortieren Erfolge
Birrel
@PKHunter: Nein. Mein schneller regulärer Ausdruck preg_match war ein einfaches Beispiel und stimmt nicht mit allen dort aufgeführten URLs überein. Siehe diese Test-URL: regex101.com/r/EpyDDc/2 Wenn Sie eine bessere wünschen, ersetzen Sie sie durch die auf Ihrem Link ( mathiasbynens.be/demo/url-regex ) von diegoperini aufgeführte. es scheint allen zu entsprechen, siehe diesen Testlink: regex101.com/r/qMQp23/1
Da viele Leute nach karim79 gefragt haben, um die cURL-Lösung zu reparieren, ist hier die Lösung, die ich heute erstellt habe.
/**
* 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
*/publicstaticfunction 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;}
Lassen Sie mich die Curl-Optionen erklären:
CURLOPT_RETURNTRANSFER : Gibt eine Zeichenfolge zurück, anstatt die aufrufende Seite auf dem Bildschirm anzuzeigen.
CURLOPT_SSL_VERIFYPEER : cUrl checkt das Zertifikat nicht aus
CURLOPT_HEADER : Fügen Sie den Header in die Zeichenfolge ein
CURLOPT_NOBODY : Fügen Sie den Body nicht in die Zeichenfolge ein
CURLOPT_USERAGENT : Einige Websites benötigen dies, um ordnungsgemäß zu funktionieren (Beispiel: https://plus.google.com ).
Zusätzlicher Hinweis : In dieser Funktion verwende ich den regulären Ausdruck von Diego Perini zum Überprüfen der URL, bevor die Anfrage gesendet wird:
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
Zusätzlicher Hinweis 2 : Ich habe die Header-Zeichenfolge und die Benutzer-Header [0] aufgelöst, um sicherzustellen, dass nur der Rückkehrcode und die Nachricht überprüft werden (Beispiel: 200, 404, 405 usw.).
Zusätzlicher Hinweis 3 : Manchmal reicht es nicht aus, nur den Code 404 zu validieren (siehe Komponententest). Daher gibt es einen optionalen Parameter $ failCodeList, um die gesamte abzulehnende Codeliste bereitzustellen.
Und hier ist natürlich der Unit-Test (einschließlich aller beliebten sozialen Netzwerke), um meine Codierung zu legitimieren:
Ich bekomme diese Ausnahme, wenn die URL existiert: Konnte die CURLOPT_HEADERFUNCTION
Safiot
3
Alle oben genannten Lösungen + zusätzlicher Zucker. (Ultimative AIO-Lösung)
/**
* 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 URIif(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)){returnfalse;}// Check that URL exists
$file_headers =@get_headers($url);return!(!$file_headers || $file_headers[0]==='HTTP/1.1 404 Not Found');}
Hier ist eine Lösung, die nur das erste Byte des Quellcodes liest ... und false zurückgibt, wenn file_get_contents fehlschlägt ... Dies funktioniert auch für entfernte Dateien wie Bilder.
function urlExists($url){if(@file_get_contents($url,false,NULL,0,1)){returntrue;}returnfalse;}
Eine andere Möglichkeit, um zu überprüfen, ob eine URL gültig ist oder nicht, ist:
<?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){returntrue;}else{returnfalse;}}?>
get_headers () gibt ein Array mit den Headern zurück, die vom Server als Antwort auf eine HTTP-Anforderung gesendet wurden.
$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>';}
Eine Sache, die Sie berücksichtigen müssen, wenn Sie den Header für einen 404 überprüfen, ist der Fall, dass eine Site nicht sofort einen 404 generiert.
Viele Websites prüfen, ob eine Seite in der PHP / ASP-Quelle (usw.) vorhanden ist oder nicht, und leiten Sie an eine 404-Seite weiter. In diesen Fällen wird der Header im Wesentlichen um den Header des generierten 404 erweitert. In diesen Fällen ist der 404-Fehler nicht in der ersten Zeile des Headers, sondern in der zehnten.
Ich führe einige Tests durch, um festzustellen, ob Links auf meiner Website gültig sind. Warnt mich, wenn Dritte ihre Links ändern. Ich hatte ein Problem mit einer Site, die ein schlecht konfiguriertes Zertifikat hatte, was bedeutete, dass die get_headers von php nicht funktionierten.
Also las ich, dass Curl schneller war und beschloss, es zu versuchen. dann hatte ich ein Problem mit LinkedIn, das mir einen 999-Fehler gab, der sich als Benutzeragentenproblem herausstellte.
Es war mir egal, ob das Zertifikat für diesen Test nicht gültig war, und es war mir egal, ob die Antwort eine Umleitung war.
Dann dachte ich mir, ich benutze sowieso get_headers, wenn die Locke fehlschlägt ...
Probieren Sie es aus....
/**
* returns true/false if the $url is present.
*
* @param string $url assumes this is a valid url.
*
* @return bool
*/privatefunction 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;}
@Jah, es ist offensichtlich nicht bei -2. Ich habe wahrscheinlich so spät in der Nacht gepostet, als ich halb eingeschlafen war, nachdem ich den ganzen Tag auf Bildschirme
Antworten:
Hier:
Von hier und direkt unter dem obigen Beitrag gibt es eine Curl- Lösung:
quelle
$file_headers[0]
Fehlerseite. Zum Beispiel youtube.com. Die Fehlerseite hat den WertHTTP/1.0 404 Not Found
(Differenz ist 1.0 und 1.1). was dann tun?strpos($headers[0], '404 Not Found')
könnte die Verwendung den Trick tunstrpos($headers[0], '404')
ist besser!Wenn Sie herausfinden möchten, ob eine URL von PHP existiert, sollten Sie einige Dinge beachten:
Denken Sie daran, dass es einige Zeit dauert, auf eine Antwort zu warten, egal welche Methode Sie verwenden.
Der gesamte Code wird möglicherweise (und wird wahrscheinlich) angehalten, bis Sie entweder das Ergebnis kennen oder die Anforderungen abgelaufen sind.
Beispiel: Der folgende Code kann lange dauern, bis die Seite angezeigt wird, wenn die URLs ungültig oder nicht erreichbar sind:
Die folgenden Funktionen könnten hilfreich sein. Sie möchten sie wahrscheinlich an Ihre Bedürfnisse anpassen:
quelle
return $code
aufif($code == 200){return true;} return false;
nur aussortieren ErfolgeJedes Mal, wenn Sie eine Website kontaktieren und etwas anderes als 200 erhalten, funktioniert es
quelle
return strpos(@get_headers($url)[0],'200') === false ? false : true
. Könnte nützlich sein.Sie können Curl auf bestimmten Servern nicht verwenden. Sie können diesen Code verwenden
quelle
quelle
quelle
Ich benutze diese Funktion:
quelle
Die get_headers () -Lösung von karim79 hat bei mir nicht funktioniert, da ich mit Pinterest verrückte Ergebnisse erzielt habe.
Wie auch immer, dieser Entwickler zeigt, dass cURL viel schneller ist als get_headers ():
http://php.net/manual/fr/function.get-headers.php#104723
Da viele Leute nach karim79 gefragt haben, um die cURL-Lösung zu reparieren, ist hier die Lösung, die ich heute erstellt habe.
Lassen Sie mich die Curl-Optionen erklären:
CURLOPT_RETURNTRANSFER : Gibt eine Zeichenfolge zurück, anstatt die aufrufende Seite auf dem Bildschirm anzuzeigen.
CURLOPT_SSL_VERIFYPEER : cUrl checkt das Zertifikat nicht aus
CURLOPT_HEADER : Fügen Sie den Header in die Zeichenfolge ein
CURLOPT_NOBODY : Fügen Sie den Body nicht in die Zeichenfolge ein
CURLOPT_USERAGENT : Einige Websites benötigen dies, um ordnungsgemäß zu funktionieren (Beispiel: https://plus.google.com ).
Zusätzlicher Hinweis : In dieser Funktion verwende ich den regulären Ausdruck von Diego Perini zum Überprüfen der URL, bevor die Anfrage gesendet wird:
Zusätzlicher Hinweis 2 : Ich habe die Header-Zeichenfolge und die Benutzer-Header [0] aufgelöst, um sicherzustellen, dass nur der Rückkehrcode und die Nachricht überprüft werden (Beispiel: 200, 404, 405 usw.).
Zusätzlicher Hinweis 3 : Manchmal reicht es nicht aus, nur den Code 404 zu validieren (siehe Komponententest). Daher gibt es einen optionalen Parameter $ failCodeList, um die gesamte abzulehnende Codeliste bereitzustellen.
Und hier ist natürlich der Unit-Test (einschließlich aller beliebten sozialen Netzwerke), um meine Codierung zu legitimieren:
Großer Erfolg an alle,
Jonathan Parent-Lévesque aus Montreal
quelle
quelle
sehr schnell:
quelle
Alle oben genannten Lösungen + zusätzlicher Zucker. (Ultimative AIO-Lösung)
Beispiel:
quelle
um zu überprüfen, ob die URL online oder offline ist ---
quelle
quelle
Hier ist eine Lösung, die nur das erste Byte des Quellcodes liest ... und false zurückgibt, wenn file_get_contents fehlschlägt ... Dies funktioniert auch für entfernte Dateien wie Bilder.
quelle
Der einfache Weg ist Curl (und SCHNELLER auch)
quelle
Eine andere Möglichkeit, um zu überprüfen, ob eine URL gültig ist oder nicht, ist:
quelle
get_headers () gibt ein Array mit den Headern zurück, die vom Server als Antwort auf eine HTTP-Anforderung gesendet wurden.
quelle
cURL kann HTTP-Code zurückgeben Ich glaube nicht, dass all dieser zusätzliche Code notwendig ist?
quelle
Eine Sache, die Sie berücksichtigen müssen, wenn Sie den Header für einen 404 überprüfen, ist der Fall, dass eine Site nicht sofort einen 404 generiert.
Viele Websites prüfen, ob eine Seite in der PHP / ASP-Quelle (usw.) vorhanden ist oder nicht, und leiten Sie an eine 404-Seite weiter. In diesen Fällen wird der Header im Wesentlichen um den Header des generierten 404 erweitert. In diesen Fällen ist der 404-Fehler nicht in der ersten Zeile des Headers, sondern in der zehnten.
quelle
Ich führe einige Tests durch, um festzustellen, ob Links auf meiner Website gültig sind. Warnt mich, wenn Dritte ihre Links ändern. Ich hatte ein Problem mit einer Site, die ein schlecht konfiguriertes Zertifikat hatte, was bedeutete, dass die get_headers von php nicht funktionierten.
Also las ich, dass Curl schneller war und beschloss, es zu versuchen. dann hatte ich ein Problem mit LinkedIn, das mir einen 999-Fehler gab, der sich als Benutzeragentenproblem herausstellte.
Es war mir egal, ob das Zertifikat für diesen Test nicht gültig war, und es war mir egal, ob die Antwort eine Umleitung war.
Dann dachte ich mir, ich benutze sowieso get_headers, wenn die Locke fehlschlägt ...
Probieren Sie es aus....
quelle
Art eines alten Threads, aber .. ich mache das:
quelle