У меня есть простой код, который выполняет запрос заголовка для 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, но служба по ссылке выше вернет ее сразу.
Что мне не хватает?
Попробуйте немного упростить его:
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. Это заставило его работать мгновенно.
Вы должны помнить, что HEAD является лишь предложением веб-сервера. Для HEAD, чтобы делать правильные вещи, это часто требует определенных явных усилий со стороны админов. Если вы HEAD статический файл Apache (или независимо от того, что ваш веб-сервер) будет часто шаг за шагом делать правильные вещи. Если вы НАЗАД динамическую страницу, по умолчанию для большинства настроек необходимо выполнить путь GET, собрать все результаты и просто отправить обратно заголовки без содержимого. Если это приложение находится в настройке уровня 3 (или более), этот вызов потенциально может быть очень дорогим и ненужным для контекста HEAD. Например, на сервлете Java по умолчанию doHead () просто вызывает doGet (). Чтобы сделать что-то более разумное для приложения, разработчику пришлось бы явно реализовать doHead () (и чаще всего это не будет).
Я столкнулся с приложением из компании, состоящей из 100 компаний, которая используется для загрузки нескольких сотен мегабайт информации о ценах. Мы проверяем наличие обновлений этих данных, выполняя запросы HEAD достаточно регулярно, пока измененная дата не изменится. Оказалось, что этот запрос фактически сделает обратные вызовы, чтобы генерировать этот список каждый раз, когда мы делали запрос, который включал гигабайты данных на их задней стороне и xfer между несколькими внутренними серверами. Они были не очень счастливы с нами, но как только мы объяснили пример использования, они быстро придумали альтернативное решение. Если бы они внедрили HEAD, а не полагались на свой веб-сервер, чтобы подделать его, это не было бы проблемой.
Я использовал функцию ниже, чтобы узнать перенаправленный URL.
$head = get_headers($url, 1);
Второй аргумент заставляет его возвращать массив с ключами. Например, ниже приведено значение Location
.
$head["Location"]
Если моя память не сбой, я делаю запрос 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);
Эта:
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
Я не пытался получить заголовки.
Я просто пытался сделать загрузку страницы некоторых данных не займет 2 минуты, как описано выше.
Этот волшебный маленький вариант снизил его до 2 секунд.