web-dev-qa-db-fra.com

Comment obtenir l'URL réelle après file_get_contents si la redirection se produit?

J'utilise file_get_contents() pour récupérer le contenu d'un site, et étonnamment cela fonctionne même si l'URL que je passe en argument redirige vers une autre URL.

Le problème est que j'ai besoin de connaître la nouvelle URL, existe-t-il un moyen de le faire?

37
HappyDeveloper

Vous pouvez faire une demande avec cURL au lieu de file_get_contents().

Quelque chose comme ça devrait fonctionner ...

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$a = curl_exec($ch);
if(preg_match('#Location: (.*)#', $a, $r))
 $l = trim($r[1]);

Source

17
alex

Si vous devez utiliser file_get_contents() au lieu de curl, ne suivez pas automatiquement les redirections:

$context = stream_context_create(
    array(
        'http' => array(
            'follow_location' => false
        )
    )
);

$html = file_get_contents('http://www.example.com/', false, $context);

var_dump($http_response_header);

Réponse inspirée par: Comment ignorer un en-tête déplacé avec file_get_contents en PHP?

54
Jakub Zalas

Tout dans une seule fonction:

function get_web_page( $url ) {
    $res = array();
    $options = array( 
        CURLOPT_RETURNTRANSFER => true,     // return web page 
        CURLOPT_HEADER         => false,    // do not return headers 
        CURLOPT_FOLLOWLOCATION => true,     // follow redirects 
        CURLOPT_USERAGENT      => "spider", // who am i 
        CURLOPT_AUTOREFERER    => true,     // set referer on redirect 
        CURLOPT_CONNECTTIMEOUT => 120,      // timeout on connect 
        CURLOPT_TIMEOUT        => 120,      // timeout on response 
        CURLOPT_MAXREDIRS      => 10,       // stop after 10 redirects 
    ); 
    $ch      = curl_init( $url ); 
    curl_setopt_array( $ch, $options ); 
    $content = curl_exec( $ch ); 
    $err     = curl_errno( $ch ); 
    $errmsg  = curl_error( $ch ); 
    $header  = curl_getinfo( $ch ); 
    curl_close( $ch ); 

    $res['content'] = $content;     
    $res['url'] = $header['url'];
    return $res; 
}  
print_r(get_web_page("http://www.example.com/redirectfrom")); 
18
Renaud

Une solution complète utilisant le nu file_get_contents (notez l'entrée-sortie $url paramètre):

function get_url_contents_and_final_url(&$url)
{
    do
    {
        $context = stream_context_create(
            array(
                "http" => array(
                    "follow_location" => false,
                ),
            )
        );

        $result = file_get_contents($url, false, $context);

        $pattern = "/^Location:\s*(.*)$/i";
        $location_headers = preg_grep($pattern, $http_response_header);

        if (!empty($location_headers) &&
            preg_match($pattern, array_values($location_headers)[0], $matches))
        {
            $url = $matches[1];
            $repeat = true;
        }
        else
        {
            $repeat = false;
        }
    }
    while ($repeat);

    return $result;
}

Notez que cela ne fonctionne qu'avec une URL absolue dans l'en-tête Location. Si vous devez prendre en charge des URL relatives, consultez PHP: Comment résoudre une URL relative .

Par exemple, si vous utilisez la solution du réponse de @Joyce Bab , remplacez:

            $url = $matches[1];

avec:

            $url = getAbsoluteURL($matches[1], $url);
1
Martin Prikryl