Algunos sitios web tienen una $file_headers[0]página de error diferente . por ejemplo, youtube.com. su página de error tiene ese valor como HTTP/1.0 404 Not Found(la diferencia es 1.0 y 1.1). que hacer entonces
Krishna Raj K
21
Quizás usar strpos($headers[0], '404 Not Found')podría hacer el truco
alexandru.topliceanu
12
@Mark estuvo de acuerdo! Para aclarar, strpos($headers[0], '404')es mejor!
alexandru.topliceanu
1
@ karim79 ten cuidado con los ataques de SSRF y XSPA
M Rostami
55
Al determinar si existe una url de php, hay algunas cosas a las que debe prestar atención:
¿Es válida la URL en sí misma (una cadena, no está vacía, buena sintaxis), esto es rápido para verificar el lado del servidor.
Esperar una respuesta puede llevar tiempo y bloquear la ejecución del código.
No todos los encabezados devueltos por get_headers () están bien formados.
Usa curl (si puedes).
Evite buscar todo el cuerpo / contenido, pero solo solicite los encabezados.
Considere redirigir las URL:
¿Quieres que te devuelva el primer código?
¿O sigue todos los redireccionamientos y devuelve el último código?
Puede terminar con un 200, pero podría redirigir usando metaetiquetas o javascript. Averiguar lo que sucede después es difícil.
Tenga en cuenta que, sea cual sea el método que utilice, lleva tiempo esperar una respuesta.
Todo el código podría (y probablemente lo hará) hasta que sepa el resultado o las solicitudes hayan expirado.
Por ejemplo: el código a continuación podría tardar MUCHO tiempo en mostrar la página si las URL no son válidas o no se pueden alcanzar:
<?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/>";}
Las siguientes funciones pueden ser útiles, probablemente desee modificarlas para satisfacer sus necesidades:
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;}
+1 por ser la única respuesta para lidiar con las redirecciones. Cambió return $codea if($code == 200){return true;} return false;para ordenar solo los éxitos
Birrel
@PKHunter: No. Mi expresión rápida preg_match regex fue un ejemplo simple y no coincidirá con todas las URL enumeradas allí. Consulte esta url de prueba: regex101.com/r/EpyDDc/2 Si desea una mejor, reemplácela por la que aparece en su enlace ( mathiasbynens.be/demo/url-regex ) de diegoperini; parece coincidir con todos ellos, vea este enlace de prueba: regex101.com/r/qMQp23/1
Dado que muchas personas pidieron que karim79 corrija es la solución cURL, aquí está la solución que construí hoy.
/**
* 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;}
Déjame explicarte las opciones de rizo:
CURLOPT_RETURNTRANSFER : devuelve una cadena en lugar de mostrar la página de llamada en la pantalla.
CURLOPT_SSL_VERIFYPEER : cUrl no pagará el certificado
CURLOPT_HEADER : incluye el encabezado en la cadena
CURLOPT_NOBODY : no incluya el cuerpo en la cadena
CURLOPT_USERAGENT : algunos sitios necesitan que funcione correctamente (por ejemplo: https://plus.google.com )
Nota adicional : en esta función estoy usando la expresión regular de Diego Perini para validar la URL antes de enviar la solicitud:
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
Nota adicional 2 : exploto la cadena de encabezado y los encabezados de usuario [0] para asegurarme de validar solo el código de retorno y el mensaje (ejemplo: 200, 404, 405, etc.)
Nota adicional 3 : en ocasiones, validar solo el código 404 no es suficiente (consulte la prueba de la unidad), por lo que hay un parámetro opcional $ failCodeList para proporcionar toda la lista de códigos para rechazar.
Y, por supuesto, aquí está la prueba unitaria (incluida toda la red social popular) para legitimar mi codificación:
obtengo esta excepción cuando existe la url: no se pudo llamar a CURLOPT_HEADERFUNCTION
safiot
3
Todas las soluciones anteriores + azúcar extra. (Última solución de AIO)
/**
* 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');}
Aquí hay una solución que lee solo el primer byte del código fuente ... devuelve falso si falla file_get_contents ... Esto también funcionará para archivos remotos como imágenes.
function urlExists($url){if(@file_get_contents($url,false,NULL,0,1)){returntrue;}returnfalse;}
Otra forma de verificar si una URL es válida o no puede ser:
<?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 () devuelve una matriz con los encabezados enviados por el servidor en respuesta a una solicitud 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>';}
Una cosa a tener en cuenta cuando verifica el encabezado de un 404 es el caso en que un sitio no genera un 404 inmediatamente.
Muchos sitios verifican si una página existe o no en la fuente PHP / ASP (etc.) y lo reenvían a una página 404. En esos casos, el encabezado se extiende básicamente por el encabezado del 404 que se genera. En esos casos, el error 404 no está en la primera línea del encabezado, sino en la décima.
Realizo algunas pruebas para ver si los enlaces en mi sitio son válidos; me avisa cuando terceros cambian sus enlaces. Estaba teniendo un problema con un sitio que tenía un certificado mal configurado que significaba que los get_headers de php no funcionaban.
Entonces, leí que el rizo era más rápido y decidí intentarlo. Luego tuve un problema con linkedin que me dio un error 999, que resultó ser un problema de agente de usuario.
No me importaba si el certificado no era válido para esta prueba, y no me importaba si la respuesta era una redirección.
Entonces pensé usar get_headers de todos modos si el rizo fallaba ...
Darle una oportunidad....
/**
* 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 obviamente no está en -2. Probablemente publicado esta tarde una noche cuando estaba medio dormido después de mirar fijamente a las pantallas todo el día ..
Respuestas:
Aquí:
Desde aquí y justo debajo de la publicación anterior, hay una solución de rizo :
fuente
$file_headers[0]
página de error diferente . por ejemplo, youtube.com. su página de error tiene ese valor comoHTTP/1.0 404 Not Found
(la diferencia es 1.0 y 1.1). que hacer entoncesstrpos($headers[0], '404 Not Found')
podría hacer el trucostrpos($headers[0], '404')
es mejor!Al determinar si existe una url de php, hay algunas cosas a las que debe prestar atención:
Tenga en cuenta que, sea cual sea el método que utilice, lleva tiempo esperar una respuesta.
Todo el código podría (y probablemente lo hará) hasta que sepa el resultado o las solicitudes hayan expirado.
Por ejemplo: el código a continuación podría tardar MUCHO tiempo en mostrar la página si las URL no son válidas o no se pueden alcanzar:
Las siguientes funciones pueden ser útiles, probablemente desee modificarlas para satisfacer sus necesidades:
fuente
return $code
aif($code == 200){return true;} return false;
para ordenar solo los éxitosasí que cada vez que contactes un sitio web y obtengas algo más que 200, funcionará
fuente
return strpos(@get_headers($url)[0],'200') === false ? false : true
. Puede ser útilno puedes usar curl en ciertos servidores puedes usar este código
fuente
fuente
fuente
Yo uso esta función:
fuente
La solución get_headers () de karim79 no funcionó para mí, ya que obtuve resultados locos con Pinterest.
De todos modos, este desarrollador demuestra que cURL es mucho más rápido que get_headers ():
http://php.net/manual/fr/function.get-headers.php#104723
Dado que muchas personas pidieron que karim79 corrija es la solución cURL, aquí está la solución que construí hoy.
Déjame explicarte las opciones de rizo:
CURLOPT_RETURNTRANSFER : devuelve una cadena en lugar de mostrar la página de llamada en la pantalla.
CURLOPT_SSL_VERIFYPEER : cUrl no pagará el certificado
CURLOPT_HEADER : incluye el encabezado en la cadena
CURLOPT_NOBODY : no incluya el cuerpo en la cadena
CURLOPT_USERAGENT : algunos sitios necesitan que funcione correctamente (por ejemplo: https://plus.google.com )
Nota adicional : en esta función estoy usando la expresión regular de Diego Perini para validar la URL antes de enviar la solicitud:
Nota adicional 2 : exploto la cadena de encabezado y los encabezados de usuario [0] para asegurarme de validar solo el código de retorno y el mensaje (ejemplo: 200, 404, 405, etc.)
Nota adicional 3 : en ocasiones, validar solo el código 404 no es suficiente (consulte la prueba de la unidad), por lo que hay un parámetro opcional $ failCodeList para proporcionar toda la lista de códigos para rechazar.
Y, por supuesto, aquí está la prueba unitaria (incluida toda la red social popular) para legitimar mi codificación:
Gran éxito para todos,
Jonathan Parent-Lévesque de Montreal
fuente
fuente
muy rápido:
fuente
Todas las soluciones anteriores + azúcar extra. (Última solución de AIO)
Ejemplo:
fuente
para verificar si la URL está en línea o fuera de línea ---
fuente
fuente
Aquí hay una solución que lee solo el primer byte del código fuente ... devuelve falso si falla file_get_contents ... Esto también funcionará para archivos remotos como imágenes.
fuente
la forma simple es curl (y también MÁS RÁPIDO)
fuente
Otra forma de verificar si una URL es válida o no puede ser:
fuente
get_headers () devuelve una matriz con los encabezados enviados por el servidor en respuesta a una solicitud HTTP.
fuente
cURL puede devolver código HTTP ¿No creo que todo ese código adicional sea necesario?
fuente
Una cosa a tener en cuenta cuando verifica el encabezado de un 404 es el caso en que un sitio no genera un 404 inmediatamente.
Muchos sitios verifican si una página existe o no en la fuente PHP / ASP (etc.) y lo reenvían a una página 404. En esos casos, el encabezado se extiende básicamente por el encabezado del 404 que se genera. En esos casos, el error 404 no está en la primera línea del encabezado, sino en la décima.
fuente
Realizo algunas pruebas para ver si los enlaces en mi sitio son válidos; me avisa cuando terceros cambian sus enlaces. Estaba teniendo un problema con un sitio que tenía un certificado mal configurado que significaba que los get_headers de php no funcionaban.
Entonces, leí que el rizo era más rápido y decidí intentarlo. Luego tuve un problema con linkedin que me dio un error 999, que resultó ser un problema de agente de usuario.
No me importaba si el certificado no era válido para esta prueba, y no me importaba si la respuesta era una redirección.
Entonces pensé usar get_headers de todos modos si el rizo fallaba ...
Darle una oportunidad....
fuente
una especie de hilo viejo, pero ... hago esto:
fuente