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 |