La mejor manera de verificar si una URL es válida

149

Quiero usar PHP para verificar, si la cadena almacenada en la $myoutputvariable contiene una sintaxis de enlace válida o es solo un texto normal. La función o solución que estoy buscando debería reconocer todos los formatos de enlaces, incluidos los que tienen parámetros GET.

En file_get_contents()mi caso, no es posible una solución, sugerida en muchos sitios, para consultar una cadena (usando CURL o función) y me gustaría evitarla.

Pensé en expresiones regulares u otra solución.

Ryan
fuente
Usar CURL u obtener su contenido HTTP puede ser lento, si desea algo más rápido y casi tan confiable, considere usar gethostbyaddr () en el nombre de host. Si se resuelve en una IP, entonces probablemente tenga un sitio web. Por supuesto, esto depende de tus necesidades.
TravisO

Respuestas:

301

Puede usar un Validador de filtro nativo

filter_var($url, FILTER_VALIDATE_URL);

Valida el valor como URL (de acuerdo con » http://www.faqs.org/rfcs/rfc2396 ), opcionalmente con los componentes necesarios. Tenga en cuenta que una URL válida puede no especificar el protocolo HTTP http: // por lo que puede ser necesaria una validación adicional para determinar que la URL utiliza un protocolo esperado, por ejemplo, ssh: // o mailto :. Tenga en cuenta que la función solo encontrará URL ASCII válidas; los nombres de dominio internacionalizados (que contienen caracteres no ASCII) fallarán.

Ejemplo:

if (filter_var($url, FILTER_VALIDATE_URL) === FALSE) {
    die('Not a valid URL');
}
Gordon
fuente
9
El comportamiento esperado de @Raveren ya que estas son URL válidas.
Gordon
8
Tenga en cuenta que FILTER_VALIDATE_URLno validará el protocolo de una url. Entonces ssh://, ftp://etc. pasará.
Seph
3
Comportamiento esperado de @SephVelut ya que se trata de URL válidas.
Gordon
1
permite URL como ttp: //amazon.com
Elia Weiss
44
@JoshHabdas, creo que te estás perdiendo el punto. El código PHP hace exactamente lo que dice hacer. Pero no puede leer tu mente. Hay una gran diferencia entre inválido y no deseado. No deseado es muy subjetivo, por lo que le queda al programador resolver esos detalles. También puede observar que el código valida la URL, pero no prueba que existe. No es culpa de PHP que un usuario haya escrito mal "amazon", "amozon", lo que podría validar, pero aún no es deseado.
JBH
20

Aquí está el mejor tutorial que encontré allí:

http://www.w3schools.com/php/filter_validate_url.asp

<?php
$url = "http://www.qbaki.com";

// Remove all illegal characters from a url
$url = filter_var($url, FILTER_SANITIZE_URL);

// Validate url
if (filter_var($url, FILTER_VALIDATE_URL) !== false) {
echo("$url is a valid URL");
} else {
echo("$url is not a valid URL");
}
?>

Posibles banderas:

FILTER_FLAG_SCHEME_REQUIRED - URL must be RFC compliant (like http://example)
FILTER_FLAG_HOST_REQUIRED - URL must include host name (like http://www.example.com)
FILTER_FLAG_PATH_REQUIRED - URL must have a path after the domain name (like www.example.com/example1/)
FILTER_FLAG_QUERY_REQUIRED - URL must have a query string (like "example.php?name=Peter&age=37")
Erich García
fuente
1
Solo un nit: !filter_var(...) === false==> filter_var(...) === trueo simplemente filter_var(...). :)
Domenico De Felice
@ ErichGarcía, este código no comprueba que sea una URL HTTP / S válida, como pregunta el OP. Esto pasará cosas como ssh: //, ftp: // etc., esto solo verifica si es una URL sintácticamente válida de acuerdo con RFC 2396
twigg
No use FILTER_VALIDATE_URL. Es desordenado y poco confiable. Por ejemplo, se valida ttps://www.youtube.comcomo válido
Jeffz
12

El uso de filter_var () fallará para las URL con caracteres no ascii, por ejemplo ( http://pt.wikipedia.org/wiki/Guimarães ). La siguiente función codifica todos los caracteres no ascii (por ejemplo, http://pt.wikipedia.org/wiki/Guimar%C3%A3es ) antes de llamar a filter_var ().

Espero que esto ayude a alguien.

<?php

function validate_url($url) {
    $path = parse_url($url, PHP_URL_PATH);
    $encoded_path = array_map('urlencode', explode('/', $path));
    $url = str_replace($path, implode('/', $encoded_path), $url);

    return filter_var($url, FILTER_VALIDATE_URL) ? true : false;
}

// example
if(!validate_url("http://somedomain.com/some/path/file1.jpg")) {
    echo "NOT A URL";
}
else {
    echo "IS A URL";
}
Huey Ly
fuente
Eso es todo. Finalmente alguien regresó en 2017
Kyle KIM
Funciona para mí (los otros no BTW) :)
Jono
Esta es la ÚNICA solución que funcionó para mí. ¡Gracias!
Silas
10
function is_url($uri){
    if(preg_match( '/^(http|https):\\/\\/[a-z0-9_]+([\\-\\.]{1}[a-z_0-9]+)*\\.[_a-z]{2,5}'.'((:[0-9]{1,5})?\\/.*)?$/i' ,$uri)){
      return $uri;
    }
    else{
        return false;
    }
}
mghhgm
fuente
3

Personalmente, me gustaría usar expresiones regulares aquí. El código de abajo funcionó perfectamente para mí.

$baseUrl     = url('/'); // for my case https://www.xrepeater.com
$posted_url  = "home";
// Test with one by one
/*$posted_url  = "/home";
$posted_url  = "xrepeater.com";
$posted_url  = "www.xrepeater.com";
$posted_url  = "http://www.xrepeater.com";
$posted_url  = "https://www.xrepeater.com";
$posted_url  = "https://xrepeater.com/services";
$posted_url  = "xrepeater.dev/home/test";
$posted_url  = "home/test";*/

$regularExpression  = "((https?|ftp)\:\/\/)?"; // SCHEME Check
$regularExpression .= "([a-z0-9+!*(),;?&=\$_.-]+(\:[a-z0-9+!*(),;?&=\$_.-]+)?@)?"; // User and Pass Check
$regularExpression .= "([a-z0-9-.]*)\.([a-z]{2,3})"; // Host or IP Check
$regularExpression .= "(\:[0-9]{2,5})?"; // Port Check
$regularExpression .= "(\/([a-z0-9+\$_-]\.?)+)*\/?"; // Path Check
$regularExpression .= "(\?[a-z+&\$_.-][a-z0-9;:@&%=+\/\$_.-]*)?"; // GET Query String Check
$regularExpression .= "(#[a-z_.-][a-z0-9+\$_.-]*)?"; // Anchor Check

if(preg_match("/^$regularExpression$/i", $posted_url)) { 
    if(preg_match("@^http|https://@i",$posted_url)) {
        $final_url = preg_replace("@(http://)+@i",'http://',$posted_url);
        // return "*** - ***Match : ".$final_url;
    }
    else { 
          $final_url = 'http://'.$posted_url;
          // return "*** / ***Match : ".$final_url;
         }
    }
else {
     if (substr($posted_url, 0, 1) === '/') { 
         // return "*** / ***Not Match :".$final_url."<br>".$baseUrl.$posted_url;
         $final_url = $baseUrl.$posted_url;
     }
     else { 
         // return "*** - ***Not Match :".$posted_url."<br>".$baseUrl."/".$posted_url;
         $final_url = $baseUrl."/".$final_url; }
}
Md. Noor-A-Alam Siddique
fuente
1
Esta es la mejor respuesta para validar URL de sitios web. Con pocos cambios esto funciona perfectamente. Gracias
Amir hossein Karimi
3

Dados problemas con filter_var () que necesitan http: //, uso:

$is_url = filter_var($filename, FILTER_VALIDATE_URL) || array_key_exists('scheme', parse_url($filename));

Otoño leonard
fuente
No use FILTER_VALIDATE_URL. Es desordenado y poco confiable. Por ejemplo, se valida ttps://www.youtube.comcomo válido
Jeffz
2

Puede usar esta función, pero devolverá falso si el sitio web está fuera de línea.

  function isValidUrl($url) {
    $url = parse_url($url);
    if (!isset($url["host"])) return false;
    return !(gethostbyname($url["host"]) == $url["host"]);
}
Hasan Veli Soyalan
fuente
2

En realidad ... filter_var ($ url, FILTER_VALIDATE_URL); no funciona muy bien Cuando escribe una url real, funciona, pero solo comprueba http: // así que si escribe algo como " http: // weirtgcyaurbatc ", seguirá diciendo que es real.

Hayden Frobenius
fuente
Para la vigencia FILTER_VALIDATE_URL valida ttps://www.youtube.comcomo válido
Jeffz
1

Otra forma de verificar si la URL dada es válida es intentar acceder a ella, la siguiente función buscará los encabezados de la URL dada, esto asegurará que la URL sea válida Y el servidor web esté vivo:

function is_url($url){
        $response = array();
        //Check if URL is empty
        if(!empty($url)) {
            $response = get_headers($url);
        }
        return (bool)in_array("HTTP/1.1 200 OK", $response, true);
/*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
)*/ 
    }   
Bud Damyanov
fuente
Buena idea. Esto fallará si el servidor está usando HTTP / 1.0 o HTTP / 2.0, o devuelve una redirección.
iblamefish
Sí, es un punto de partida, se pueden hacer más mejoras fácilmente.
Bud Damyanov
1

Encontré este artículo a partir de 2012. Tiene en cuenta variables que pueden o no ser solo URL simples.

El autor del artículo, David Müeller , proporciona esta función que dice, "... podría valer la pena [sic]", junto con algunos ejemplos filter_vary sus defectos.

/**
 * Modified version of `filter_var`.
 *
 * @param  mixed $url Could be a URL or possibly much more.
 * @return bool
 */
function validate_url( $url ) {
    $url = trim( $url );

    return (
        ( strpos( $url, 'http://' ) === 0 || strpos( $url, 'https://' ) === 0 ) &&
        filter_var(
            $url,
            FILTER_VALIDATE_URL,
            FILTER_FLAG_SCHEME_REQUIRED || FILTER_FLAG_HOST_REQUIRED
        ) !== false
    );
}
DaveyJake
fuente
0

si alguien está interesado en usar el cURL para la validación. Puedes usar el siguiente código.

<?php 
public function validationUrl($Url){
        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);
        return ($httpcode >= 200 && $httpcode < 300) ? true : false; 
    }
VishalParkash
fuente