当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);
?>
答案 0 :(得分:47)
您可以使用:
echo curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
答案 1 :(得分:22)
$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';
答案 2 :(得分:6)
有点过时的回复,但希望展示一个完整的工作示例,其中一些解决方案有:
$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上它只会返回请求的原始网址(因为找不到它)。这可用于更新或删除您网站的链接。无论如何,这是我的需要。
答案 3 :(得分:5)
您必须抓住重定向网址的位置标头。
答案 4 :(得分:2)
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
只需用正则表达式进行grep。
要包含所有HTTP标头信息,请将其包含在curl选项 CURLOPT_HEADER 的结果中。设置为:
curl_setopt($c, CURLOPT_HEADER, true);
如果您只想让curl遵循重定向,请使用 CURLOPT_FOLLOWLOCATION :
curl_setopt($c, CURLOPT_FOLLOWLOCATION, true);
无论如何,您不应该使用新的URI,因为HTTP状态码302只是临时重定向。
答案 5 :(得分:2)
回应用户437797对Tamik Soziev的回答的评论(遗憾的是我没有直接在那里发表评论的声誉):
CURLINFO_EFFECTIVE_URL工作正常,但要像op那样做,你当然也必须将CURLOPT_FOLLOWLOCATION设置为TRUE。这是因为CURLINFO_EFFECTIVE_URL完全返回它所说的内容,即最终加载的有效URL。如果您不遵循重定向,那么这将是您请求的URL,如果您确实遵循重定向,那么它将是重定向到的最终URL。
这种方法的好处在于它也适用于多个重定向,而在自己检索和解析HTTP头时,您可能需要多次执行此操作才能显示最终目标URL。
另请注意,可以通过CURLOPT_MAXREDIRS控制卷曲所遵循的最大重定向数。默认情况下它是无限制的(-1)但如果有人(可能是有意)配置并且为某些网址重复无限循环,这可能会让你陷入麻烦。
答案 6 :(得分:1)
这是一种获取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);
}
答案 7 :(得分:0)
使用curl_getinfo($ch)
,第一个元素(url
)表示有效网址。