Найкращий спосіб перевірити, чи дійсна URL-адреса


149

Я хочу використовувати PHP, щоб перевірити, чи рядок, що зберігається в $myoutputзмінній, містить дійсний синтаксис посилання або це просто звичайний текст. Я шукаю функцією або рішенням, повинен розпізнавати всі формати посилань, включаючи типи з параметрами GET.

Запропоновано на багатьох сайтах рішення фактичного запиту рядка (використовуючи CURL або file_get_contents()функцію) в моєму випадку неможливо, і я хотів би його уникнути.

Я думав про регулярні вирази чи інше рішення.


Використання CURL або отримання його вмісту HTTP може бути повільним, якщо ви хочете щось більш швидке і майже таке ж надійне, подумайте про використання gethostbyaddr () на ім'я хоста. Якщо він вирішує IP, то, ймовірно, він має веб-сайт. Звичайно, це залежить від ваших потреб.
TravisO

Відповіді:


301

Можна скористатись нативною програмою Validator Filter

filter_var($url, FILTER_VALIDATE_URL);

Перевіряє значення як URL (згідно з " http://www.faqs.org/rfcs/rfc2396 ), необов'язково з необхідними компонентами. Остерігайтесь, щоб дійсна URL-адреса не могла вказати протокол HTTP http: //, тому для визначення URL-адреси, що очікується, потрібна додаткова перевірка, наприклад, ssh: // або mailto :. Зверніть увагу, що функція знайде лише URL-адреси ASCII, які є дійсними; інтернаціоналізовані доменні імена (містять символи, що не належать до ASCII) не зможуть.

Приклад:

if (filter_var($url, FILTER_VALIDATE_URL) === FALSE) {
    die('Not a valid URL');
}

9
@Raveren очікувана поведінка, оскільки це дійсні URL-адреси.
Гордон

8
Будьте в курсі, що FILTER_VALIDATE_URLпротокол URL не підтверджує. Отже ssh://, ftp://тощо пройде.
Сефі

3
@SephVelut очікувана поведінка, оскільки це дійсні URL-адреси.
Гордон

1
це дозволяє URL-адреси на зразок ttp: //amazon.com
Елія Вайс

4
@JoshHabdas, я думаю, ти пропускаєш суть. PHP-код робить саме те, що він вимагає зробити. Але він не може прочитати вашу думку. Існує величезна різниця між недійсним та небажаним. Небажане дуже суб'єктивне, тому програміст залишає розробити цю деталь. Ви також можете відзначити, що код підтверджує URL-адресу, але не доводить, що він існує. Це не вина PHP, що користувач вводив помилково "amazon", "amozon", який би підтвердив, але все ще є небажаним.
JBH

20

Ось найкращий підручник, який я там знайшов:

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");
}
?>

Можливі прапори:

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")

1
Просто ніт: !filter_var(...) === false==> filter_var(...) === trueабо просто filter_var(...). :)
Доменіко Де Феліче

@ ErichGarcía цей код не перевіряє, що це дійсна URL-адреса HTTP / S, як запитує ОП. Це передасть такі речі, як ssh: //, ftp: // і т.
Д.,

Не використовуйте FILTER_VALIDATE_URL. Це безладно і ненадійно. Наприклад, це підтверджує свою ttps://www.youtube.comдійсність
Джеффз

12

Використання filter_var () не вдасться для URL-адрес із символами, що не мають права ascii, наприклад ( http://pt.wikipedia.org/wiki/Guimarães ). Наступна функція кодує всі символи, що не відносяться до ascii (наприклад, http://pt.wikipedia.org/wiki/Guimar%C3%A3es ) перед викликом filter_var ().

Сподіваюся, що це комусь допоможе.

<?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";
}

Це воно. Нарешті хтось повернувся у 2017 році
Кайл КІМ

Працює для мене (інші - не BTW) :)
Jono

Це ТІЛЬКЕ рішення, яке працювало на мене. Дякую!
Сілас

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;
    }
}

3

Особисто я хотів би тут використовувати регулярне вираження. Нижній код ідеально працював для мене.

$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; }
}

1
Це найкраща відповідь на підтвердження URL-адрес веб-сайтів. Маючи кілька змін, це працює чудово. Спасибі
Амір Хоссен Карімі

3

Подані проблеми з filter_var (), які потребують http: //, я використовую:

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


Не використовуйте FILTER_VALIDATE_URL. Це безладно і ненадійно. Наприклад, це підтверджує свою ttps://www.youtube.comдійсність
Джеффз

2

Ви можете використовувати цю функцію, але вона повернеться помилковою, якщо веб-сайт в автономному режимі.

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

2

Насправді ... filter_var ($ url, FILTER_VALIDATE_URL); працює не дуже добре. Коли ви вводите справжній URL, він працює, але він перевіряє лише http: //, тому якщо ви введете щось на кшталт " http: // weirtgcyaurbatc ", воно все одно скаже, що це реально.


Для примірника FILTER_VALIDATE_URL перевіряється ttps://www.youtube.comяк дійсне
Jeffz

1

Інший спосіб перевірити , якщо даний URL діє, щоб спробувати отримати до нього доступ, нижче функції буде отримувати заголовки з даного URL, це буде гарантувати , що URL є дійсним і веб - сервер живий:

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
)*/ 
    }   

Хороша ідея. Це не вдасться, якщо сервер використовує HTTP / 1.0 або HTTP / 2.0, або поверне переспрямування.
iblamefish

Так, це відправна точка, подальше вдосконалення можна зробити легко.
Буд Дамянов

1

Подається ця стаття з 2012 року. Вона враховує змінні, які можуть бути, а можуть бути не просто простими URL-адресами.

Автор статті Девід Мюллер забезпечує цю функцію, яку він каже, "... може бути вартий хитрості", а також деякі приклади filter_varта її недоліки.

/**
 * 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
    );
}

0

якщо хтось зацікавлений використовувати CURL для перевірки. Можна використовувати наступний код.

<?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; 
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.