Когда требуется получить HTTP код для заданной URL, то вы наверняка воспользуетесь PHP функцией get_headers($url). Дальше я расскажу о разных подводных камнях и возникающих попутных проблемах.
В первом приближении задача решается элементарно. У вас есть URL, вы запрашиваете только заголовки, т.к. вам не нужен сам документ. В заголовках можно найти и пропарсить стандартный ответ сервера, чтобы извлечь код ответа.
1 2 3 4 |
$URL = 'какая то ваша ссылка'; $headers = get_headers($URL); echo $code = substr($headers[0], 9, 3); // в теории, выведет HTTP код ответа сервера. |
Скорее всего, вы действительно получите желаемое, но не всегда. Потому перейдем к рассмотрению наиболее частых коллизий.
Домен не существует
Да такое бывает, когда введенный адрес не существует. Вернее не адрес, а доменное имя сайта. Запрос посылать некуда, а вы увидите (если не отключили вывод php warnings) что то вроде следующего:
PHP вернет пустые заголовки, из которых ничего не извлечь. Как можно обработать эту ситуацию?
1 2 3 4 5 6 7 8 |
// отключим вывод ошибок в функции get_headers $headers = @get_headers($URL); if (empty($headers[0])) { $code = 'no response'; } else { $code = substr($headers[0], 9, 3); } echo $code; |
Тут вы уже не увидите сообщений от PHP, а в случае невозможности определить адрес сервера — будет установлено какое то кастомное значение вместо HTTP кода, чтобы иметь возможность его обработать дальше.
Доменные имена с использованием национальных наборов символов.
Функция get_headers не настолько умна, чтобы переводить ваш http://россия.рф в http://xn--h1alffa9f.xn--p1ai200.
Если вы попытаетесь запросить заголовки без перевода в нужный вид, то прошлый пример выдаст вам загадочное ‘no response’. В то время как браузер без проблем откроет сайт, т.к. умеет переводить доменные имена, в которых используются местные национальные наборы символов, отличные от латиницы.
Для конвертации используем свободно распространяемую библиотеку idna_convert. Качайте архив, распаковывайте и подключайте в ваш код.
Теперь пример выглядит следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 |
require_once 'class.idna_convert.php'; $URL = 'http://россия.рф'; $idn = new idna_convert(array('idn_version'=>2008)); $URL = $idn->encode($URL); $headers = @get_headers($URL); if (empty($headers[0])) { $code = 'no response'; } else { $code = substr($headers[0], 9, 3); } |
Ошибки с SSL сертификатами
Если вы делаете запросы к https:// сайтам, то рано или поздно увидите ошибки вроде : «SSL error SSL3_GET_SERVER_CERTIFICATE:certificate verify failed». Ничего страшного, сейчас мы укажем PHP, что не время проводить проверки SSL сертификатов.
Воспользуемся контекстом потока, для задания необходимых параметров. Перед кодом нужно добавить:
1 2 3 4 5 6 7 8 9 10 11 |
$contextOptions = array( 'ssl' => array( 'verify_peer' => false, 'verify_peer_name' => false ) ); // установлен контекст с флагами, запрещающими проверку SSL сертификата stream_context_set_default($contextOptions); // ну и дальше уже знакомый код ... |
С 7-й версии PHP контекст можно передать как третий параметр get_headers(). Для этого его нужно создать функцией stream_context_create ([ array $options [, array $params ]] ).