PHP / Curl: запрос HEAD занимает много времени на некоторых сайтах - PullRequest
25 голосов
/ 21 апреля 2009

У меня есть простой код, который выполняет запрос заголовка для 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 ]

43 голосов
/ 21 апреля 2009

Попробуйте немного упростить:

print htmlentities(file_get_contents("http://www.arstechnica.com"));

Вышеуказанные данные немедленно выводятся на мой веб-сервер. Если это не относится к вашему, есть большая вероятность, что у вашего веб-хостинга есть какие-то настройки для регулирования таких запросов.

EDIT

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

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. Это заставило его работать мгновенно.

7 голосов
/ 21 апреля 2009

Вы должны помнить, что HEAD - это всего лишь предложение для веб-сервера. Чтобы HEAD делал правильные вещи, часто требуются определенные усилия со стороны администраторов. Если вы НАЧИНАЕТЕ статический файл, Apache (или любой другой веб-сервер) часто вмешивается и делает правильные вещи. Если вы возглавляете динамическую страницу, по умолчанию для большинства установок используется выполнение пути GET, сбор всех результатов и просто отправка обратно заголовков без содержимого. Если это приложение настроено на 3 (или более) уровня, этот вызов потенциально может быть очень дорогим и ненужным для контекста HEAD. Например, в Java-сервлете по умолчанию doHead () просто вызывает doGet (). Чтобы сделать что-то более умное для приложения, разработчик должен явно реализовать doHead () (и чаще всего этого не будет).

Я столкнулся с приложением от компании из списка 100, которое используется для загрузки нескольких сотен мегабайт информации о ценах. Мы проверяли бы обновления этих данных, выполняя запросы HEAD довольно регулярно, пока не изменилась дата изменения. Оказывается, что этот запрос будет фактически вызывать внутренние вызовы для генерации этого списка каждый раз, когда мы выполняем запрос, который включает гигабайты данных на их внутреннем конце и перенаправляет его между несколькими внутренними серверами. Они не были очень довольны нами, но как только мы объяснили сценарий использования, они быстро нашли альтернативное решение. Если бы они внедрили HEAD, вместо того чтобы полагаться на свой веб-сервер, чтобы подделать его, это не было бы проблемой.

4 голосов
/ 21 апреля 2009

Если моя память не перестает работать, я выполняю запрос 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);
3 голосов
/ 23 июля 2011

Я использовал приведенную ниже функцию, чтобы узнать перенаправленный URL.

$head = get_headers($url, 1);

Второй аргумент заставляет его возвращать массив с ключами. Например, ниже приведено значение Location.

$head["Location"]

http://php.net/manual/en/function.get-headers.php

0 голосов
/ 01 марта 2011

Это:

curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);

Я не пытался получить заголовки.
Я просто пытался заставить страницу загружать некоторые данные, не занимая 2 минуты, как описано выше.
Этот волшебный маленький выбор опустил его до 2 секунд.

...