重定向后的 HTTP 响应代码
有一个重定向到服务器以获取信息,一旦响应来自服务器,我想检查 HTTP 代码以在有任何以 4XX 开头的代码时抛出异常.为此,我需要知道如何从标头中仅获取 HTTP 代码?这里也涉及到服务器的重定向,所以我担心 curl 对我没有用.
There is a redirect to server for information and once response comes from server, I want to check HTTP code to throw an exception if there is any code starting with 4XX. For that I need to know how can I get only HTTP code from header? Also here redirection to server is involved so I afraid curl will not be useful to me.
到目前为止,我已经尝试过 此解决方案,但它非常慢并且会在我的情况.我不想增加脚本超时时间并等待更长的时间来获取 HTTP 代码.
So far I have tried this solution but it's very slow and creates script time out in my case. I don't want to increase script time out period and wait longer just to get an HTTP code.
提前感谢您的任何建议.
Thanks in advance for any suggestion.
推荐答案
您使用 get_headers
并请求第一个响应行的方法将返回重定向的状态代码(如果有)并且 更重要的是,它会发出一个 GET 请求来传输整个文件.
Your method with get_headers
and requesting the first response line will return the status code of the redirect (if any) and more importantly, it will do a GET request which will transfer the whole file.
您只需要一个 HEAD 请求,然后解析标头并返回 last 状态码.以下是执行此操作的代码示例,它使用 $http_response_header
而不是 get_headers
,但数组的格式相同:
You need only a HEAD request and then to parse the headers and return the last status code. Following is a code example that does this, it's using $http_response_header
instead of get_headers
, but the format of the array is the same:
$url = 'http://example.com/';
$options['http'] = array(
'method' => "HEAD",
'ignore_errors' => 1,
);
$context = stream_context_create($options);
$body = file_get_contents($url, NULL, $context);
$responses = parse_http_response_header($http_response_header);
$code = $responses[0]['status']['code']; // last status code
echo "Status code (after all redirects): $code<br>
";
$number = count($responses);
$redirects = $number - 1;
echo "Number of responses: $number ($redirects Redirect(s))<br>
";
if ($redirects)
{
$from = $url;
foreach (array_reverse($responses) as $response)
{
if (!isset($response['fields']['LOCATION']))
break;
$location = $response['fields']['LOCATION'];
$code = $response['status']['code'];
echo " * $from -- $code --> $location<br>
";
$from = $location;
}
echo "<br>
";
}
/**
* parse_http_response_header
*
* @param array $headers as in $http_response_header
* @return array status and headers grouped by response, last first
*/
function parse_http_response_header(array $headers)
{
$responses = array();
$buffer = NULL;
foreach ($headers as $header)
{
if ('HTTP/' === substr($header, 0, 5))
{
// add buffer on top of all responses
if ($buffer) array_unshift($responses, $buffer);
$buffer = array();
list($version, $code, $phrase) = explode(' ', $header, 3) + array('', FALSE, '');
$buffer['status'] = array(
'line' => $header,
'version' => $version,
'code' => (int) $code,
'phrase' => $phrase
);
$fields = &$buffer['fields'];
$fields = array();
continue;
}
list($name, $value) = explode(': ', $header, 2) + array('', '');
// header-names are case insensitive
$name = strtoupper($name);
// values of multiple fields with the same name are normalized into
// a comma separated list (HTTP/1.0+1.1)
if (isset($fields[$name]))
{
$value = $fields[$name].','.$value;
}
$fields[$name] = $value;
}
unset($fields); // remove reference
array_unshift($responses, $buffer);
return $responses;
}
更多信息参见:HEAD first withPHP Streams,最后包含示例代码,您也可以使用 get_headers
执行 HEAD 请求.
For more information see: HEAD first with PHP Streams, at the end it contains example code how you can do the HEAD request with get_headers
as well.
相关:如何可以使用 PHP 检查远程文件是否存在吗?
相关文章