Проблемы с редиректом для CURL

Совершенно внезапно выяснилось что 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 и уже с ним функция вызывает рекурсивно саму себя.

По логике надо еще сделать защиту от зацикливания. Но это не должно представлять проблем для человека, который знает как писать рекурсивные функции.

Запись опубликована в рубрике Фриланс с метками . Добавьте в закладки постоянную ссылку.

Добавить комментарий