如果发生重定向,如何在 file_get_contents 之后获取真实的 URL?

Posted

技术标签:

【中文标题】如果发生重定向,如何在 file_get_contents 之后获取真实的 URL?【英文标题】:How to get the real URL after file_get_contents if redirection happens? 【发布时间】:2011-05-18 11:05:31 【问题描述】:

我正在使用 file_get_contents() 从站点中获取内容,令人惊讶的是,即使我作为参数传递的 URL 重定向到另一个 URL,它也能正常工作。

问题是我需要知道新的 URL,有没有办法做到这一点?

【问题讨论】:

【参考方案1】:

如果您需要使用file_get_contents() 而不是 curl,请不要自动跟随重定向:

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

答案灵感来自:How do I ignore a moved-header with file_get_contents in php?

【讨论】:

你从哪里得到$http_response_header @PetrPeller 这是一个 PHP 特殊变量:php.net/manual/en/reserved.variables.httpresponseheader.php 我试过了,虽然它确实根据这个答案末尾链接的问题停止了重定向,但它没有提供这个问题中要求的“真实 URL”。不过,也可能是我尝试使用的服务器不支持它。在我看来,虽然 curl() 方法是唯一可靠的方法。 @RPorter 你需要提取$http_response_header中的301位置。 具有保留名称的神奇局部变量,实际上是保存先前函数调用结果的全局变量... PHP 是一团乱七八糟的语言。【参考方案2】:

您可以使用 cURL 而不是 file_get_contents() 发出请求。

这样的东西应该可以工作......

$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

【讨论】:

谢谢.. 但是我从哪里获得 html 输出呢?在 $a 我只能看到标题。是否有可能只用一个请求就可以得到一切?编辑:好吧,那是愚蠢的。现在我明白了,无论如何都会有 2 个请求 =D。谢谢! 但是如果有多个重定向呢?如何获取最终到达网址? CURL 在 Google App 引擎中不可用,因此如果您需要使用 file_get_contents(),答案无济于事 @ixlli 对。我一定错过了 OP 所说的答案必须仅适用于 Google App Engine 环境 @alex heh... 我认为关键是他在询问 file_get_contents() 所以当谷歌搜索问题时,这就是你发现的。【参考方案3】:

一切尽在一个功能中:

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

【讨论】:

小心。 CURLOPT_FOLLOWLOCATION 在“open_base_dir”被填满或启用安全模式时是不允许的。【参考方案4】:

使用裸file_get_contents 的完整解决方案(注意输入输出$url 参数):

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;


请注意,这仅适用于 Location 标头中的绝对 URL。如果您需要支持相对 URL,请参阅 PHP: How to resolve a relative url.

例如,如果您使用answer by @Joyce Babu 中的解决方案,请替换:

            $url = $matches[1];

与:

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

【讨论】:

【参考方案5】:

我用get_headers($url, 1);

在我的情况下,get_headers($url, 1)['Location'][1];中的重定向网址

【讨论】:

以上是关于如果发生重定向,如何在 file_get_contents 之后获取真实的 URL?的主要内容,如果未能解决你的问题,请参考以下文章

如果发生数据库错误,如何将页面重定向到其他页面

servlet发生异常时如何重定向到错误页面?

从file_get_contents()成功获取数据后,PHP重定向到另一个页面

如何解决Stripe元素的react导致重定向内存泄漏的问题。

node.js 请求获取重定向链

如何在快速应用程序上正确发送重定向到 URL