Получение и валидация URL из POST-запроса в PHP

Раздел: PHP -> Работа с POST-запросами: приём

Основные подходы к приёму ссылок

Наиболее эффективное решение: получение и валидация URL через filter_var

Принять ссылку из POST-запроса можно через суперглобальный массив $_POST. Однако безопасность требует проверки и очистки данных. Оптимальный способ - сочетание filter_var с флагом FILTER_VALIDATE_URL и функция экранирования htmlspecialchars для вывода.


$rawUrl = $_POST['link'] ?? '';
$validatedUrl = filter_var($rawUrl, FILTER_VALIDATE_URL);
if ($validatedUrl !== false) {
    $safeUrl = htmlspecialchars($validatedUrl, ENT_QUOTES, 'UTF-8');
    echo "Получен корректный URL: $safeUrl";
} else {
    echo "Переданная строка не является валидным URL";
}
  

Php post array (массив $_post в php)

Этот блок проверяет, что в $_POST['link'] действительно содержится URL (согласно стандарту), а затем безопасно выводит его. Если проверка не пройдена, выводится сообщение об ошибке.

Типичная проблема:

Фильтр FILTER_VALIDATE_URL не пропускает многие реально работающие адреса, например, содержащие кириллицу (IDN) или localhost без точки. Решение - дополнительная кастомная проверка или использование расширения intl для декодирования IDN.

Простое присваивание без валидации

Вопрос: как принять ссылку без какой-либо проверки, если обрабатывается только внутренний трафик?


$link = $_POST['url'] ?? '';
  

Php параметры post (параметры post-запроса в php)

Однако это опасно: при выводе такой ссылки без экранирования возникает XSS. Если ссылка сохраняется в БД, она также должна быть экранирована при вставке.

Риски:

Вставка неэкранированного значения в HTML может привести к внедрению скриптов. Даже при внутреннем использовании стоит применить htmlspecialchars.

Разбор URL на компоненты

Вопрос: как извлечь схему, хост, путь из переданной ссылки для дальнейшего анализа?

Функция parse_url разбивает URL на ассоциативный массив.


$url = $_POST['link'];
$parts = parse_url($url);
if ($parts !== false) {
    echo 'Схема: ' . ($parts['scheme'] ?? 'не указана') . "\n";
    echo 'Хост: ' . ($parts['host'] ?? 'не указан') . "\n";
    echo 'Путь: ' . ($parts['path'] ?? 'не указан') . "\n";
}
  

Php post link (работа со ссылками в post-запросе php)

Особенности:

parse_url не проверяет валидность URL как такового, только разбирает строку. Для нестандартных схем (например, ftp://) может работать некорректно.

Преобразование относительной ссылки в абсолютную

Вопрос: как дополнить относительный путь до полного URL, используя базовый адрес?


$base = 'https://example.com';
$relative = $_POST['path'];
// Используем parse_url для объединения
if (strpos($relative, '://') === false) {
    $absolute = rtrim($base, '/') . '/' . ltrim($relative, '/');
} else {
    $absolute = $relative;
}
echo $absolute;
  

Более надёжное решение - использование класса Normalizer из библиотеки или функции stream_resolve_include_path.

Проверка доступности ссылки через cURL

Вопрос: как убедиться, что переданный URL ведёт на реально существующий ресурс?


$url = filter_var($_POST['link'], FILTER_VALIDATE_URL);
if ($url !== false) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 5);
    curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    if ($httpCode >= 200 && $httpCode < 400) {
        echo "Ссылка доступна (HTTP $httpCode)";
    } else {
        echo "Ссылка недоступна (HTTP $httpCode)";
    }
} else {
    echo "Некорректный URL";
}
  

Ограничения:

Запрос cURL может замедлить обработку, особенно при ожидании таймаута. Не рекомендуется выполнять такие проверки при каждом запросе. Лучше асинхронно или кешировать результаты.

Сохрание ссылки в базу данных с защитой

Вопрос: как записать принятую ссылку в MySQL, избегая SQL-инъекций?


$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$stmt = $pdo->prepare('INSERT INTO links (url) VALUES (:url)');
$stmt->execute([':url' => $validatedUrl]);
  

Валидация перед вставкой обязательна, а также экранирование через подготовленные запросы.

Расширенные примеры работы с ссылками в POST-запросах

Пример

// Пример 1: Декодирование IDN (интернациональных доменов)
$url = 'http://пример.рф';
$encoded = idn_to_ascii($url, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46);
echo "ASCII форма: $encoded\n";
$decoded = idn_to_utf8($encoded, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46);
echo "UTF-8 форма: $decoded\n";
ASCII форма: http://xn--e1afmkfd.xn--p1ai
UTF-8 форма: http://пример.рф
Пример

// Пример 2: Извлечение домена второго уровня и TLD
$url = $_POST['site'];
$parsed = parse_url($url);
$host = $parsed['host'] ?? '';
$parts = explode('.', $host);
$domain = $parts[count($parts)-2] ?? '';
$tld = $parts[count($parts)-1] ?? '';
echo "Домен: $domain, TLD: $tld";
Домен: example, TLD: com
Пример

// Пример 3: Преобразование ссылки с параметрами в ассоциативный массив
$url = 'https://example.com/page?name=John&age=30';
$query = parse_url($url, PHP_URL_QUERY);
parse_str($query, $params);
print_r($params);
Array
(
    [name] => John
    [age] => 30
)
Пример

// Пример 4: Проверка на принадлежность домена к белому списку
$whitelist = ['example.com', 'mysite.org'];
$url = $_POST['link'];
$host = parse_url($url, PHP_URL_HOST);
if (in_array($host, $whitelist)) {
    echo "Разрешённый домен";
} else {
    echo "Домен не в белом списке";
}
Разрешённый домен
Пример

// Пример 5: Формирование короткой ссылки (внутренняя логика)
$longUrl = $_POST['long_url'];
$shortCode = substr(md5($longUrl . time()), 0, 8);
$shortUrl = "https://short.example/$shortCode";
echo "Короткая ссылка: $shortUrl";
Короткая ссылка: https://short.example/a1b2c3d4

Важно:

Во всех примерах, где данные выводятся на страницу, необходимо использовать htmlspecialchars для защиты от XSS. Также при работе с внешними URL стоит учитывать возможность перенаправлений и вредоносного контента.

Работа со ссылками в POST-запросе PHP - comments

En
Php post link (php)