Определение имени хоста в PHP: от простого к сложному
Получение имени хоста в PHP: основные методы
Основное и наиболее часто используемое решение
Для получения имени хоста, с которого пришел HTTP-запрос, чаще всего применяется значение суперглобального массива $_SERVER['HTTP_HOST']. Оно содержит имя хоста и порт (если порт нестандартный), переданные клиентом в заголовке Host.
<?php
$host = $_SERVER['HTTP_HOST'] ?? null;
echo $host;
?>Php имя хоста (получение имени хоста в php)
Если запрос выполнен через браузер, результатом будет, например, example.com или example.com:8080.
Возможные проблемы:
- При выполнении скрипта в командной строке (CLI) массив
$_SERVERможет не содержать ключаHTTP_HOST. В таких случаях следует использоватьgethostname()(см. варианты ниже). - Значение
HTTP_HOSTможет быть подделано клиентом, поэтому для критичных операций (например, проверка домена в URL) рекомендуется дополнительная валидация, например, через список разрешенных имен или сравнение с$_SERVER['SERVER_NAME'].
Как получить системное имя хоста (независимо от HTTP-запроса)?
Функция gethostname() возвращает имя локального компьютера, установленное в операционной системе. Она подходит для CLI-скриптов, демонов, а также для веб-окружения, если необходимо узнать имя сервера, а не имя, переданное в запросе.
<?php
echo gethostname();
?>имя user php (получение имени пользователя в php)
Результат: server01.example.com или просто server01.
Особенности:
- Результат может не совпадать с доменным именем, используемым клиентами для обращения к сайту.
- В некоторых окружениях (например, контейнеры Docker) значение может быть идентификатором контейнера.
Как получить имя хоста из переменной SERVER_NAME?
Переменная $_SERVER['SERVER_NAME'] содержит имя хоста, указанное в конфигурации сервера (директива ServerName для Apache). В отличие от HTTP_HOST, это значение задается администратором и не может быть подделано клиентом.
<?php
echo $_SERVER['SERVER_NAME'];
?>
Результат: www.example.com.
Проблемы:
- Если сервер настроен на несколько виртуальных хостов,
SERVER_NAMEможет соответствовать имени хоста, заданному в конфигурации для текущего запроса, но это не гарантируется во всех веб-серверах (например, Nginx может передавать значение из заголовка Host). - Порт не включается; при необходимости его нужно получать отдельно через
$_SERVER['SERVER_PORT'].
Как получить полное доменное имя (FQDN) сервера?
Можно использовать комбинацию gethostbyaddr() и IP-адреса сервера. Эта функция выполняет обратный DNS-запрос.
<?php
$ip = $_SERVER['SERVER_ADDR'] ?? gethostbyname(gethostname());
$fqdn = gethostbyaddr($ip);
echo $fqdn;
?>
Результат: mail.example.com или unknown при отсутствии PTR-записи.
Важно:
- Обратный DNS-запрос может занимать время или завершаться таймаутом.
- Если PTR-запись отсутствует, возвращается IP-адрес.
Как получить имя хоста без зависимостей от HTTP-контекста?
Функция php_uname('n') возвращает имя хоста аналогично команде uname -n в Unix или hostname в Windows. Это системное имя, не зависящее от веб-сервера.
<?php
echo php_uname('n');
?>
Результат: myhost.
Расширенные примеры работы с именем хоста
Пример 1. Сравнение HTTP_HOST и SERVER_NAME при виртуальных хостах
Предположим, веб-сервер обрабатывает запросы для доменов site1.ru и site2.ru на одном IP. Клиент может отправить заголовок Host: site1.ru, а сервер может быть настроен с ServerName site2.ru. Различие может привести к неверному определению:
<?php
echo 'HTTP_HOST: ' . ($_SERVER['HTTP_HOST'] ?? 'не задан') . "\n";
echo 'SERVER_NAME: ' . ($_SERVER['SERVER_NAME'] ?? 'не задан');
?>
HTTP_HOST: site1.ru SERVER_NAME: site2.ru
Для сайтов, работающих через HTTPS, порт может быть опущен, но заголовок Host всё равно передается.
Пример 2. Безопасное получение имени хоста с валидацией
Чтобы избежать использования поддельного имени, следует проверить значение через белый список или сравнить с SERVER_NAME:
<?php
$allowedHosts = ['example.com', 'www.example.com'];
$host = $_SERVER['HTTP_HOST'] ?? '';
// Удаляем порт
$hostOnly = explode(':', $host)[0];
if (in_array($hostOnly, $allowedHosts, true)) {
echo 'Допустимый хост: ' . $hostOnly;
} else {
echo 'Хост не входит в список разрешенных.';
}
?>
Пример 3. Получение имени хоста в CLI-скрипте с разными подходами
При запуске скрипта из командной строки $_SERVER['HTTP_HOST'] отсутствует. Используем gethostname() и php_uname('n'):
<?php
echo 'gethostname(): ' . gethostname() . "\n";
echo 'php_uname("n"): ' . php_uname('n') . "\n";
echo 'getenv("HOSTNAME"): ' . (getenv('HOSTNAME') ?: 'не задана') . "\n";
?>
gethostname(): my-server
php_uname("n"): my-server
getenv("HOSTNAME"): my-server
Пример 4. Обратное разрешение IP в доменное имя с таймаутом
Если необходимо получить FQDN, но избежать долгого ожидания, можно воспользоваться сокетами или задать ограничение через proc_open(), однако проще использовать gethostbyaddr() и принять возможную задержку:
<?php
$ip = '8.8.8.8';
$hostname = gethostbyaddr($ip);
echo "Адрес $ip соответствует: $hostname";
?>
Адрес 8.8.8.8 соответствует: dns.google
Пример 5. Извлечение имени хоста из полного URL
Иногда требуется получить имя хоста из произвольного URL, например, из строки редиректа. Используется функция parse_url():
<?php
$url = 'https://user:pass@sub.example.com:8080/path?q=1#frag';
$parts = parse_url($url);
echo 'host: ' . $parts['host'] . "\n";
echo 'port: ' . ($parts['port'] ?? 'не указан');
?>
host: sub.example.com port: 8080