PHP:如何发送HTTP响应代码?

时间:2010-07-15 18:23:57

标签: php http-response-codes

我有一个PHP脚本,需要使用HTTP响应代码(状态代码)进行响应,例如HTTP 200 OK或某些4XX或5XX代码。

我如何在PHP中执行此操作?

9 个答案:

答案 0 :(得分:403)

我刚发现这个问题并认为需要更全面的答案:

PHP 5.4 开始,有三种方法可以实现此目的:

自行组装响应代码(PHP> = 4.0)

header()函数有一个特殊用例,用于检测HTTP响应行,并允许您将其替换为自定义

header("HTTP/1.1 200 OK");

但是,这需要对(快速)CGI PHP进行特殊处理:

$sapi_type = php_sapi_name();
if (substr($sapi_type, 0, 3) == 'cgi')
    header("Status: 404 Not Found");
else
    header("HTTP/1.1 404 Not Found");

注意:根据HTTP RFC原因短语可以是任何自定义字符串(符合标准),但为了客户端兼容性我建议在那里放一个随机字符串。

注意: php_sapi_name()需要 PHP 4.0.1

标题函数的第3个参数(PHP> = 4.3)

使用第一个变体时显然存在一些问题。我认为其中最大的部分是由PHP或Web服务器部分解析而且文档记录不足。

从4.3开始,header函数有一个第三个参数,可以让你轻松地设置响应代码,但使用它需要第一个参数为非空字符串。这有两个选择:

header(':', true, 404);
header('X-PHP-Response-Code: 404', true, 404);

我推荐第二个。第一个 适用于我测试过的所有浏览器,但是一些次要浏览器或网络抓取工具可能会遇到只包含冒号的标题行的问题。第2个中的标题字段名称。变体当然没有以任何方式标准化并且可以修改,我只是选择了一个有希望的描述性名称。

http_response_code函数(PHP> = 5.4)

PHP {5.4}中引入了http_response_code()函数,它使很多更容易。

http_response_code(404);

就是这样。

兼容性

这是我在需要低于5.4的兼容性但我想要“新”http_response_code函数的功能时已经编写的函数。我相信PHP 4.3具有足够的向后兼容性,但你永远不会知道......

// For 4.3.0 <= PHP <= 5.4.0
if (!function_exists('http_response_code'))
{
    function http_response_code($newcode = NULL)
    {
        static $code = 200;
        if($newcode !== NULL)
        {
            header('X-PHP-Response-Code: '.$newcode, true, $newcode);
            if(!headers_sent())
                $code = $newcode;
        }       
        return $code;
    }
}

答案 1 :(得分:34)

不幸的是,我发现@dualed提出的解决方案存在各种缺陷。

  1. 使用substr($sapi_type, 0, 3) == 'cgi'无法检测到快速CGI。使用PHP-FPM FastCGI流程管理器时,php_sapi_name()返回fpm而不是cgi

  2. Fasctcgi和php-fpm暴露了@Josh提到的另一个错误 - 使用header('X-PHP-Response-Code: 404', true, 404);在PHP-FPM(FastCGI)下正常工作

  3. 当协议不是HTTP / 1.1(即&#39; HTTP / 1.0&#39;)时,
  4. header("HTTP/1.1 404 Not Found");可能会失败。必须使用$_SERVER['SERVER_PROTOCOL']检测当前协议(自PHP 4.1.0起可用

  5. 调用http_response_code()导致意外行为时,至少有两种情况:

    • 当PHP遇到它不理解的HTTP响应代码时,PHP将用它在同一组中知道的代码替换代码。例如&#34; 521 Web服务器已关闭&#34;被&#34; 500内部服务器错误&#34;取代。来自其他组2xx,3xx,4xx的许多其他不常见的响应代码都是以这种方式处理的。
    • 在具有php-fpm和nginx的服务器上,http_response_code()函数可以按预期更改代码,但不能更改消息。这可能会导致一个奇怪的&#34; 404 OK&#34;标题例如。用户评论http://www.php.net/manual/en/function.http-response-code.php#112423
    • 在PHP网站上也提到了这个问题
  6. 此处提供了完整的HTTP响应状态代码列表(此列表包括来自IETF互联网标准以及其他IETF RFC的代码。许多PHP目前不支持PHP http_response_code函数):{{3} }

    您可以通过致电:

    轻松测试此错误
    http_response_code(521);
    

    服务器将发送&#34; 500内部服务器错误&#34;如果您有一个自定义客户端应用程序调用您的服务器并期望一些额外的HTTP代码,则HTTP响应代码会导致意外错误。


    我的解决方案(适用于4.1.0以来的所有PHP版本):

    $httpStatusCode = 521;
    $httpStatusMsg  = 'Web server is down';
    $phpSapiName    = substr(php_sapi_name(), 0, 3);
    if ($phpSapiName == 'cgi' || $phpSapiName == 'fpm') {
        header('Status: '.$httpStatusCode.' '.$httpStatusMsg);
    } else {
        $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0';
        header($protocol.' '.$httpStatusCode.' '.$httpStatusMsg);
    }
    

    <强>结论

    http_response_code()实现不支持所有HTTP响应代码,并且可能会使用同一组中的另一个覆盖指定的HTTP响应代码。

    新的http_response_code()函数并没有解决所有涉及的问题,但是最糟糕的是引入了新的错误。

    &#34;兼容性&#34; @dualed提供的解决方案不能按预期工作,至少在PHP-FPM下。

    @dualed提供的其他解决方案也存在各种错误。快速CGI检测不能处理PHP-FPM。必须检测当前协议。

    感谢任何测试和评论。

答案 2 :(得分:12)

自PHP 5.4起,您可以使用http_response_code()获取和设置标题状态代码。

这里有一个例子:

<?php

// Get the current response code and set a new one
var_dump(http_response_code(404));

// Get the new response code
var_dump(http_response_code());
?>

这是php.net中此函数的文档:

http_response_code

答案 3 :(得分:7)

如果您没有使用输出缓冲,请在身体的任何输出之前添加此行。

header("HTTP/1.1 200 OK");

将消息部分(“确定”)替换为相应的消息,并使用适当的代码替换状态代码(404,501等)

答案 4 :(得分:6)

如果你因为Wordpress在加载环境时提供404而来到这里,这应该可以解决问题:

define('WP_USE_THEMES', false);
require('../wp-blog-header.php');
status_header( 200 );
//$wp_query->is_404=false; // if necessary

问题是由于它发送了Status:404 Not Found标头。你必须覆盖它。 这也有效:

define('WP_USE_THEMES', false);
require('../wp-blog-header.php');
header("HTTP/1.1 200 OK");
header("Status: 200 All rosy");

答案 5 :(得分:5)

使用header功能。在第一个参数的部分中有一个例子。

答案 6 :(得分:1)

header("HTTP/1.1 200 OK");
http_response_code(201);

http_response_code(200);因为测试警报404而无法工作 https://developers.google.com/speed/pagespeed/insights/

答案 7 :(得分:1)

如果您的PHP版本不包含此功能:

<?php

function http_response_code($code = NULL) {
        if ($code !== NULL) {
            switch ($code) {
                case 100: $text = 'Continue';
                    break;
                case 101: $text = 'Switching Protocols';
                    break;
                case 200: $text = 'OK';
                    break;
                case 201: $text = 'Created';
                    break;
                case 202: $text = 'Accepted';
                    break;
                case 203: $text = 'Non-Authoritative Information';
                    break;
                case 204: $text = 'No Content';
                    break;
                case 205: $text = 'Reset Content';
                    break;
                case 206: $text = 'Partial Content';
                    break;
                case 300: $text = 'Multiple Choices';
                    break;
                case 301: $text = 'Moved Permanently';
                    break;
                case 302: $text = 'Moved Temporarily';
                    break;
                case 303: $text = 'See Other';
                    break;
                case 304: $text = 'Not Modified';
                    break;
                case 305: $text = 'Use Proxy';
                    break;
                case 400: $text = 'Bad Request';
                    break;
                case 401: $text = 'Unauthorized';
                    break;
                case 402: $text = 'Payment Required';
                    break;
                case 403: $text = 'Forbidden';
                    break;
                case 404: $text = 'Not Found';
                    break;
                case 405: $text = 'Method Not Allowed';
                    break;
                case 406: $text = 'Not Acceptable';
                    break;
                case 407: $text = 'Proxy Authentication Required';
                    break;
                case 408: $text = 'Request Time-out';
                    break;
                case 409: $text = 'Conflict';
                    break;
                case 410: $text = 'Gone';
                    break;
                case 411: $text = 'Length Required';
                    break;
                case 412: $text = 'Precondition Failed';
                    break;
                case 413: $text = 'Request Entity Too Large';
                    break;
                case 414: $text = 'Request-URI Too Large';
                    break;
                case 415: $text = 'Unsupported Media Type';
                    break;
                case 500: $text = 'Internal Server Error';
                    break;
                case 501: $text = 'Not Implemented';
                    break;
                case 502: $text = 'Bad Gateway';
                    break;
                case 503: $text = 'Service Unavailable';
                    break;
                case 504: $text = 'Gateway Time-out';
                    break;
                case 505: $text = 'HTTP Version not supported';
                    break;
                default:
                    exit('Unknown http status code "' . htmlentities($code) . '"');
                    break;
            }
            $protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
            header($protocol . ' ' . $code . ' ' . $text);
            $GLOBALS['http_response_code'] = $code;
        } else {
            $code = (isset($GLOBALS['http_response_code']) ? $GLOBALS['http_response_code'] : 200);
        }
        return $code;
    }

答案 8 :(得分:0)

我们可以通过两个不同的环境从http_response_code获得不同的返回值:

  1. Web服务器环境
  2. CLI环境

在Web服务器环境中,如果您提供了响应代码,则返回先前的响应代码,或者当您不提供任何响应代码时,将打印当前值。默认值为200(确定)。

在CLI环境中,如果您提供了响应代码,则将返回true;如果您未提供任何response_code,则将返回false。

Response_code返回值的Web服务器环境示例:

var_dump(http_respone_code(500)); // int(200)
var_dump(http_response_code()); // int(500)

Response_code返回值的CLI环境示例:

var_dump(http_response_code()); // bool(false)
var_dump(http_response_code(501)); // bool(true)
var_dump(http_response_code()); // int(501)