重定向后的 HTTP 响应代码

发布于 2024-12-06 10:39:30 字数 314 浏览 0 评论 0原文

有一个到服务器的信息重定向,一旦来自服务器的响应,我想检查 HTTP 代码以抛出异常(如果有任何以 4XX 开头的代码)。为此,我需要知道如何从标头中仅获取 HTTP 代码?这里还涉及到服务器的重定向,所以我担心curl 对我来说没有用。

到目前为止,我已经尝试了 此解决方案,但它非常慢,并且在我的情况下会导致脚本超时。我不想增加脚本超时时间并等待更长的时间来获取 HTTP 代码。

预先感谢您的任何建议。

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.

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

傲娇萝莉攻 2024-12-13 10:39:30

使用 get_headers 并请求第一个响应行的方法将返回重定向的状态代码(如果有)更重要的是,它将执行 GET 请求,该请求将传输整个文件。

您只需要一个 HEAD 请求,然后解析标头并返回 last 状态代码。以下是执行此操作的代码示例,它使用 $http_response_header 而不是 get_headers,但数组的格式是相同的:

$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>\n";

$number = count($responses);

$redirects = $number - 1;

echo "Number of responses: $number ($redirects Redirect(s))<br>\n";

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>\n";
        $from = $location;
    }
    echo "<br>\n";
}

/**
 * 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 首先使用 PHP Streams,最后包含如何使用 get_headers 执行 HEAD 请求的示例代码。

相关:如何检查使用 PHP 查看远程文件是否存在?

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.

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>\n";

$number = count($responses);

$redirects = $number - 1;

echo "Number of responses: $number ($redirects Redirect(s))<br>\n";

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>\n";
        $from = $location;
    }
    echo "<br>\n";
}

/**
 * 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;
}

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.

Related: How can one check to see if a remote file exists using PHP?

反差帅 2024-12-13 10:39:30

例如:

  $ch = curl_init(); 
  $httpcode = curl_getinfo ($ch, CURLINFO_HTTP_CODE );

您应该尝试 HttpEngine 类。
希望这有帮助。

-

编辑

$ch = curl_init();
curl_setopt($ch, CURLOPT_USERAGENT, $your_agent_variable);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_REFERER, $your_referer);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$output = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpcode ...)

Something like:

  $ch = curl_init(); 
  $httpcode = curl_getinfo ($ch, CURLINFO_HTTP_CODE );

You should try the HttpEngine Class.
Hope this helps.

--

EDIT

$ch = curl_init();
curl_setopt($ch, CURLOPT_USERAGENT, $your_agent_variable);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_REFERER, $your_referer);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$output = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpcode ...)
挽清梦 2024-12-13 10:39:30

您找到的解决方案看起来不错。如果服务器无法及时向您发送 http 标头,则问题是另一台服务器已损坏或负载非常重。

The solution you found looks good. If the server is not able to send you the http headers in time your problem is that the other server is broken or under very heavy load.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文