PHP / Curl: HEAD Запрос занимает много времени на некоторых сайтах
У меня есть простой код, который выполняет запрос заголовка для URL, а затем печатает заголовки ответа. Я заметил, что на некоторых сайтах это может занять много времени.
Например, запрашивая http://www.arstechnica.com
занимает около двух минут. Я попробовал тот же запрос, используя другой веб-сайт, который выполняет ту же основную задачу, и он возвращается немедленно. Таким образом, должно быть что-то, что я установил неправильно, что вызывает эту задержку.
Вот код, который у меня есть:
$ch = curl_init();
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 20);
curl_setopt ($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
// Only calling the head
curl_setopt($ch, CURLOPT_HEADER, true); // header will be at output
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'HEAD'); // HTTP request is 'HEAD'
$content = curl_exec ($ch);
curl_close ($ch);
Вот ссылка на веб-сайт, который выполняет ту же функцию: http://www.seoconsultants.com/tools/headers.asp
Приведенный выше код, по крайней мере, на моем сервере, занимает две минуты для поиска www.arstechnica.com, но служба по ссылке выше возвращает его сразу же.
Что мне не хватает?
5 ответов
Попробуйте немного упростить это:
print htmlentities(file_get_contents("http://www.arstechnica.com"));
Вышеуказанные выводы мгновенно выводятся на мой веб-сервер. Если это не относится к вашему, есть большая вероятность, что у вашего веб-хостинга есть какие-то настройки для регулирования таких запросов.
РЕДАКТИРОВАТЬ:
Поскольку вышеизложенное происходит мгновенно, попробуйте установить эту настройку скручивания на свой исходный код:
curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, true);
Используя инструмент, который вы разместили, я заметил, что http://www.arstechnica.com
имеет заголовок 301, отправленный для любого запроса, отправленного ему. Возможно, что cURL получает это и не следует новому указанному ему местоположению, что приводит к зависанию вашего скрипта.
ВТОРОЙ РЕДАКТИРОВАТЬ:
Как ни странно, при попытке использовать тот же код, что и у вас выше, мой веб-сервер тоже зависал. Я заменил этот код:
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'HEAD'); // HTTP request is 'HEAD'
С этим:
curl_setopt($ch, CURLOPT_NOBODY, true);
Именно так руководство рекомендует вам сделать запрос HEAD. Это заставило его работать мгновенно.
Вы должны помнить, что HEAD - это всего лишь предложение для веб-сервера. Чтобы HEAD делал все правильно, администраторам часто требуются определенные усилия. Если вы НАЧИНАЕТЕ статический файл, Apache (или какой-либо другой веб-сервер) часто вмешивается и делает правильные вещи. Если вы возглавляете динамическую страницу, по умолчанию для большинства установок используется выполнение пути GET, сбор всех результатов и просто отправка обратно заголовков без содержимого. Если это приложение настроено на 3 (или более) уровня, этот вызов потенциально может быть очень дорогим и ненужным для контекста HEAD. Например, в Java-сервлете по умолчанию doHead () просто вызывает doGet (). Чтобы сделать что-то более умное для приложения, разработчик должен был бы явно реализовать doHead () (и чаще всего они не будут).
Я столкнулся с приложением от компании из списка 100, которое загружает несколько сотен мегабайт информации о ценах. Мы будем проверять наличие обновлений этих данных, выполняя запросы HEAD довольно регулярно, пока дата изменения не изменится. Оказывается, что этот запрос будет фактически вызывать внутренние вызовы для генерации этого списка каждый раз, когда мы выполняем запрос, который включает гигабайты данных на их внутреннем конце и пересылает его между несколькими внутренними серверами. Они не были очень довольны нами, но как только мы объяснили сценарий использования, они быстро нашли альтернативное решение. Если бы они внедрили HEAD, вместо того чтобы полагаться на свой веб-сервер, чтобы подделать его, это не было бы проблемой.
Если моя память не перестает работать, я выполняю запрос HEAD в CURL, изменяя версию протокола HTTP на 1.0 (что является медленной и, вероятно, виновной частью) здесь, попробуйте изменить это на:
$ch = curl_init();
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 20);
curl_setopt ($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
// Only calling the head
curl_setopt($ch, CURLOPT_HEADER, true); // header will be at output
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'HEAD'); // HTTP request is 'HEAD'
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); // ADD THIS
$content = curl_exec ($ch);
curl_close ($ch);
Я использовал приведенную ниже функцию, чтобы узнать перенаправленный URL.
$head = get_headers($url, 1);
Второй аргумент заставляет его возвращать массив с ключами. Например, ниже приведен Location
значение.
$head["Location"]
Это:
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
Я не пытался получить заголовки.
Я просто пытался заставить страницу загружать некоторые данные, не занимая 2 минуты, как описано выше.
Этот волшебный маленький выбор опустил его до 2 секунд.