web-dev-qa-db-fra.com

Comment puis-je obtenir l'URL de destination à l'aide de cURL?

Comment puis-je obtenir l'URL de destination à l'aide de cURL lorsque le code d'état HTTP est 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);
?>
34
ahmed

Vous pouvez utiliser:

echo curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
49
Tamik Soziev
$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';
22
Leksat

Un peu daté d'une réponse, mais je voulais montrer un exemple de travail complet, certaines des solutions sont des morceaux:

    $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);

Cela fonctionne avec toutes les redirections telles que 301 ou 302, mais sur les 404, il retournera simplement l'URL d'origine demandée (car elle n'a pas été trouvée). Cela peut être utilisé pour mettre à jour ou supprimer des liens de votre site. C'était mon besoin de toute façon.

8
Shawn

Vous devez saisir l'en-tête Location pour l'URL redirigée.

5
raspi

En réponse au commentaire de user437797 sur la réponse de Tamik Soziev (je n'ai malheureusement pas la réputation de commenter directement):

Le CURLINFO_EFFECTIVE_URL fonctionne bien, mais pour qu'il fonctionne comme vous le souhaitez, vous devez également définir CURLOPT_FOLLOWLOCATION sur TRUE bien sûr. En effet, CURLINFO_EFFECTIVE_URL renvoie exactement ce qu'il dit, l'URL effective qui finit par être chargée. Si vous ne suivez pas les redirections, ce sera votre URL demandée, si vous suivez les redirections, ce sera l'url finale qui sera redirigée.

La bonne chose à propos de cette approche est qu'elle fonctionne également avec plusieurs redirections, tandis que lorsque vous récupérez et analysez vous-même l'en-tête HTTP, vous devrez peut-être le faire plusieurs fois avant que l'URL de destination finale ne soit exposée.

Notez également que le nombre maximum de redirections que curl suit peut être contrôlé via CURLOPT_MAXREDIRS. Par défaut, il est illimité (-1) mais cela peut vous causer des ennuis si quelqu'un (peut-être intentionnellement) a configuré une boucle de redirection sans fin pour une URL.

3
Arthur

La nouvelle destination d'une redirection 302 est située dans le champ d'en-tête http "emplacement". Exemple:

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

Il suffit de le grep avec une expression régulière.

Pour inclure toutes les informations d'en-tête HTTP, incluez-les dans le résultat avec l'option curl CURLOPT_HEADER. Réglez-le avec:

curl_setopt($c, CURLOPT_HEADER, true);

Si vous voulez simplement que curl suive la redirection, utilisez CURLOPT_FOLLOWLOCATION:

curl_setopt($c, CURLOPT_FOLLOWLOCATION, true);

Quoi qu'il en soit, vous ne devez pas utiliser le nouvel URI car HTTP Statuscode 302 n'est qu'une redirection temporaire.

2
echox

Voici un moyen d'obtenir tous les en-têtes retournés par une requête http curl, ainsi que le code d'état et un tableau de lignes d'en-tête pour chaque en-tête.

$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);
}
1
GZipp

Utilisez curl_getinfo($ch) et le premier élément (url) indiquerait l'URL effective.

0
Sabeen Malik