【问题标题】:How can I get the destination URL using cURL?如何使用 cURL 获取目标 URL?
【发布时间】:2025-11-24 21:55:02
【问题描述】:

当 HTTP 状态码为 302 时,如何使用 cURL 获取目标 URL?

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

【问题讨论】:

  • 其他未解决的问题有什么好运气吗?
  • 你应该接受正确答案(-1)

标签: php html http curl


【解决方案1】:

你可以使用:

echo curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);

【讨论】:

  • 这种方法比从 Location 标头中解析出 url 要干净得多/通常更好。
  • CURLINFO_EFFECTIVE_URL 为我返回当前(请求的)页面。 curl_getinfo 结果中没有重定向 (Location:) url。看来,解析标头是最好的做法......
  • CURLINFO_EFFECTIVE_URL 在某些情况下并不总是有效,尤其是那些不使用标头重定向的情况。
  • 对于那些正在获取当前(请求)页面的人,在调用 curl_exec($ch); 后使用此代码
  • 很好,比自己解析要干净得多。感谢分享!
【解决方案2】:
$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';

【讨论】:

  • 完美!感谢分享
  • 如果没有位置标头?
  • 有时网站会使用元重定向或window.location.replace 来重定向页面。在这种情况下,请替换正则表达式以捕获结果。
【解决方案3】:

回复有点过时,但想展示一个完整的工作示例,其中一些解决方案是:

    $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(因为它没有找到)。这可用于更新或删除您网站上的链接。无论如何,这是我的需要。

【讨论】:

    【解决方案4】:

    您必须获取重定向 URL 的 Location 标头。

    【讨论】:

    • 这需要进一步的麻烦,比如检查它是否是相对的,解决它(如果有多个等,则在中间重定向中可能是以前的基本 URL 等。pp。),它更容易使用@ 987654321@.
    【解决方案5】:

    作为对 user437797 对 Tamik Soziev 回答的评论的回应(不幸的是,我没有直接在那里发表评论的声誉):

    CURLINFO_EFFECTIVE_URL 可以正常工作,但要按照操作的要求进行操作,您当然还必须将 CURLOPT_FOLLOWLOCATION 设置为 TRUE。这是因为 CURLINFO_EFFECTIVE_URL 准确地返回它所说的,最终被加载的有效 url。如果您不遵循重定向,那么这将是您请求的 url,如果您遵循重定向,那么它将是重定向到的最终 url。

    这种方法的好处是它也适用于多个重定向,而当您自己检索和解析 HTTP 标头时,您可能必须在最终目标 URL 公开之前多次执行此操作。

    另请注意,curl 遵循的最大重定向数可以通过 CURLOPT_MAXREDIRS 控制。默认情况下它是无限制的(-1),但如果有人(可能是故意)为某些 url 配置了无限的重定向循环,这可能会给您带来麻烦。

    【讨论】:

      【解决方案6】:

      302 重定向的新目的地位于 http 标头字段“位置”中。 示例:

      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
      

      只需用正则表达式 grep 即可。

      要包含所有 HTTP 标头信息,请使用 curl 选项 CURLOPT_HEADER 将其包含到结果中。设置它:

      curl_setopt($c, CURLOPT_HEADER, true);
      

      如果您只是想让 curl 跟随重定向,请使用 CURLOPT_FOLLOWLOCATION

      curl_setopt($c, CURLOPT_FOLLOWLOCATION, true);
      

      无论如何,您不应该使用新的 URI,因为 HTTP 状态码 302 只是一个临时重定向。

      【讨论】:

        【解决方案7】:

        这是一种获取 curl http 请求返回的所有标头的方法,以及每个标头的状态代码和标头行数组。

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

        【讨论】:

          【解决方案8】:

          使用curl_getinfo($ch),第一个元素(url)表示有效网址。

          【讨论】: