cURL и переадресация
В идеале, для того, чтобы cURL в PHP автоматичесски "отлавливал" переадресацию по HTTP-заголовку 301 или 302, следует использовать константу CURLOPT_FOLLOWLOCATION, но на практике, как часто это бывает, все не так просто. В случае использования safe_mode или open_basedir php огорчает такой ошибкой: Warning: curl_setopt() : CURLOPT_FOLLOWLOCATION cannot be activated when in safe_mode or an open_basedir is set in ... Поскольку safe_mode, а особенно, open_basedir используются весьма часто, и возможности их отключить зачастую нет, необходимо использовать обходные пути.
Для начала следует принять заголовки, отдаваемые сервером. Реализуется это так - PHP-скрипт ниже:
$ch = curl_init('http://yandex.ru');
curl_setopt($ch, CURLOPT_HEADER, 1); // Отображать в ответе заголовки
curl_setopt($ch, CURLOPT_NOBODY, 1); // Неотображать текст самой страницы
$header = curl_exec($ch);
curl_close($ch);
echo $header;
Изучив заголовки, полученные в ответе при помощи cURL, находим Location - это и будет адрес перенаправления.
HTTP/1.1 301 Moved Permanently Date: Sun, 10 Jul 2011 01:05:45 GMT Server: Apache/2.2.9 (Unix) mod_perl/2.0.4 Perl/v5.12.1 Location: http://www.yandex.ru/ Vary: Accept-Encoding Connection: close Content-Type: text/html; charset=iso-8859-1
Первоначально, Яндекс пересылает всех посетителей, с адреса без www на адрес с www.
Чтобы автоматически переходить по всем редиректам (с защитой от зацикливания), можно использовать код на PHP c cURL и функцию, опубликованную ниже.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://yandex.ru');
curl_setopt($ch, CURLOPT_TIMEOUT, 10); // Сколько сек. ждать ответ сервреа
$page = curl_redir_exec($ch);
$page = curl_exec($ch);
curl_close($ch);
echo $page;
function curl_redir_exec($ch)
{
static $curl_loops = 0;
static $curl_max_loops = 20;
if ($curl_loops >= $curl_max_loops)
{
$curl_loops = 0;
return false;
}
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
list($header, $data) = explode("\n\n", $data, 2);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($http_code == 301 || $http_code == 302)
{
$matches = array();
preg_match('/Location:(.*?)\n/', $header, $matches);
$url = @parse_url(trim(array_pop($matches)));
if (!$url)
{
$curl_loops = 0;
return $data;
}
$last_url = parse_url(curl_getinfo($ch, CURLINFO_EFFECTIVE_URL));
if (!$url['scheme'])
$url['scheme'] = $last_url['scheme'];
if (!$url['host'])
$url['host'] = $last_url['host'];
if (!$url['path'])
$url['path'] = $last_url['path'];
$new_url = $url['scheme'] . '://' . $url['host'] . $url['path'] . ($url['query']?'?'.$url['query']:'');
echo $new_url.' --- '.$http_code.'<br>';
curl_setopt($ch, CURLOPT_URL, $new_url);
return curl_redir_exec($ch);
}
else
{
$curl_loops = 0;
return $data;
}
}
Этот скрипт php является готовым решением для перехода по редиректам с помощью cURL.
Полезные ссылки |
| Официальная документация по cURL (eng) |
| Примеры использования cURL |
| Статьи об cURL |