Как я могу получить целевой URL с помощью cURL? - PullRequest
34 голосов
/ 17 сентября 2009

Как я могу получить целевой URL с помощью cURL, если код состояния HTTP 302?

<?PHP
$url = "http://www.ecs.soton.ac.uk/news/";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$html = curl_exec($ch);
$status_code = curl_getinfo($ch,CURLINFO_HTTP_CODE);

if($status_code=302 or $status_code=301){
  $url = "";
  // I want to to get the destination url
}
curl_close($ch);
?>

Ответы [ 8 ]

47 голосов
/ 07 февраля 2011

Вы можете использовать:

echo curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
22 голосов
/ 28 июля 2012
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HEADER, TRUE); // We'll parse redirect url from header.
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE); // We want to just get redirect url but not to follow it.
$response = curl_exec($ch);
preg_match_all('/^Location:(.*)$/mi', $response, $matches);
curl_close($ch);
echo !empty($matches[1]) ? trim($matches[1][0]) : 'No redirect found';
7 голосов
/ 10 января 2014

Немного устаревший от ответа, но хотел показать полный рабочий пример, некоторые решения есть кусочки:

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url); //set url
    curl_setopt($ch, CURLOPT_HEADER, true); //get header
    curl_setopt($ch, CURLOPT_NOBODY, true); //do not include response body
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); //do not show in browser the response
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); //follow any redirects
    curl_exec($ch);
    $new_url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL); //extract the url from the header response
    curl_close($ch);

Это работает с любыми перенаправлениями, такими как 301 или 302, однако на 404 он просто вернет исходный запрошенный URL (так как он не был найден). Это может быть использовано для обновления или удаления ссылок с вашего сайта. В любом случае, это было моей потребностью.

5 голосов
/ 17 сентября 2009

Вы должны получить заголовок Местоположение для перенаправленного URL.

3 голосов
/ 18 февраля 2014

В ответ на комментарий user437797 к ответу Тамика Созиева (к сожалению, у меня нет репутации, чтобы комментировать там напрямую):

CURLINFO_EFFECTIVE_URL работает нормально, но для того, чтобы он действовал так, как хочет операционная система, вы также должны установить для CURLOPT_FOLLOWLOCATION значение TRUE, конечно. Это потому, что CURLINFO_EFFECTIVE_URL возвращает именно то, что говорит, эффективный URL, который в итоге загружается. Если вы не следуете перенаправлениям, тогда это будет запрошенный вами URL, если вы будете следовать перенаправлениям, это будет последний URL, на который перенаправляется.

Приятной особенностью этого подхода является то, что он также работает с несколькими перенаправлениями, тогда как при самостоятельном получении и разборе HTTP-заголовка вам может потребоваться сделать это несколько раз, прежде чем будет отображен окончательный URL-адрес назначения.

Также обратите внимание, что максимальное количество перенаправлений, которые следует за curl, может управляться через CURLOPT_MAXREDIRS. По умолчанию оно не ограничено (-1), но это может привести к неприятностям, если кто-то (возможно, намеренно) настроит бесконечный цикл перенаправления для некоторого URL.

2 голосов
/ 17 сентября 2009

Новый пункт назначения для перенаправления 302 находится в поле заголовка http "location". Пример:

HTTP/1.1 302 Found
Date: Tue, 30 Jun 2002 1:20:30 GMT
Server: Apache
Location: http://www.foobar.com/foo/bar
Content-Type: text/html; charset=iso-8859-1

Просто добавьте это в регулярное выражение.

Чтобы включить всю информацию заголовка HTTP, включите ее в результат с параметром curl CURLOPT_HEADER . Установите его с помощью:

curl_setopt($c, CURLOPT_HEADER, true);

Если вы просто хотите, чтобы curl следовал за перенаправлением, используйте CURLOPT_FOLLOWLOCATION :

curl_setopt($c, CURLOPT_FOLLOWLOCATION, true);

В любом случае, вы не должны использовать новый URI, потому что HTTP Statuscode 302 является только временным перенаправлением.

1 голос
/ 17 сентября 2009

Вот способ получить все заголовки, возвращаемые запросом HTTP curl, а также код состояния и массив строк заголовка для каждого заголовка.

$url = 'http://google.com';
$opts = array(CURLOPT_URL => $url,
              CURLOPT_RETURNTRANSFER => true,
              CURLOPT_HEADER => true,
              CURLOPT_FOLLOWLOCATION => true);

$ch = curl_init();
curl_setopt_array($ch, $opts);
$return = curl_exec($ch);
curl_close($ch);

$headers = http_response_headers($return);
foreach ($headers as $header) {
    $str = http_response_code($header);
    $hdr_arr = http_response_header_lines($header);
    if (isset($hdr_arr['Location'])) {
        $str .= ' - Location: ' . $hdr_arr['Location'];
    }
    echo $str . '<br />';
}

function http_response_headers($ret_str)
{
    $hdrs = array();
    $arr = explode("\r\n\r\n", $ret_str);
    foreach ($arr as $each) {
        if (substr($each, 0, 4) == 'HTTP') {
            $hdrs[] = $each;
        }
    }
    return $hdrs;
}

function http_response_header_lines($hdr_str)
{
    $lines = explode("\n", $hdr_str);
    $hdr_arr['status_line'] = trim(array_shift($lines));
    foreach ($lines as $line) {
        list($key, $val) = explode(':', $line, 2);
        $hdr_arr[trim($key)] = trim($val);
    }
    return $hdr_arr;
}

function http_response_code($str)
{
    return substr(trim(strstr($str, ' ')), 0, 3);
}
0 голосов
/ 23 сентября 2009

Используйте curl_getinfo($ch), и первый элемент (url) будет указывать действующий URL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...