Совершенно внезапно выяснилось что cURL не всегда поддерживает автоматический редирект. Существует хорошая возможность, которая включается следующим образом:
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
Это указывает cURL что в случае если при загрузке указанного URL будет получен редирект (т.е. статус 301 или 302) то будет автоматически осуществлен переход и загрузка страницы по новому адресу. Удобно и практично. Но не всегда.
Оказывается что из-за соображений безопастности эта опция может игнорироваться. И тогда получаем сообщение об ошибке:
Warning: curl_setopt(): CURLOPT_FOLLOWLOCATION cannot be activated when safe_mode is enabled or an open_basedir is set
И соответственно редирект автоматически не срабатывает. Получить такой сюрприз можно на шаред хостингах где включен режим safe_mode или же установленно ограничение для open_basedir
И можно к гадалке не ходить — хостер не отключит данные настройки безопастности ради вас. И его можно понять.
А нам надо искать обходные пути 🙂
Самым простым и легким для меня оказалось сделать самостоятельную обработку заголовка Location:. Рассказываю как
Изначально вся работа с cURL у меня ведется через сапописную функцию make_curl — я ей URL — она мне содержимое страницы.
Поэтому в данную функцию добавил инициализацию следующего параметра
curl_setopt($ch, CURLOPT_HEADER, true);
Таким образом в результате ответа кроме содержимого страницы появились еще и HTTP заголовки.
В самом конце функции, перед тем как вернуть результат работы вместо
$result = curl_exec ($ch); curl_close ($ch); return $result;
добавил следующий код
$result = curl_exec ($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($code == 301 || $code == 302) { preg_match('/Location:(.*?)\n/', $result, $matches); $newurl = trim(array_pop($matches)); curl_close ($ch); return make_curl($newurl); } curl_close ($ch); return $result;
Т.е. обрабатывается случай редиректа (код статуса 301 или 302), из заголовков вырезается новый URL и уже с ним функция вызывает рекурсивно саму себя.
По логике надо еще сделать защиту от зацикливания. Но это не должно представлять проблем для человека, который знает как писать рекурсивные функции.