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

如何在PHP中做到这一点?


当前回答

如果你在这里是因为Wordpress在加载环境时给出404错误,这应该可以解决这个问题:

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

该问题是由于它发送一个状态:404 Not Found头。你必须重写它。 这也可以:

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

其他回答

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

Using substr($sapi_type, 0, 3) == 'cgi' is not enogh to detect fast CGI. When using PHP-FPM FastCGI Process Manager, php_sapi_name() returns fpm not cgi Fasctcgi and php-fpm expose another bug mentioned by @Josh - using header('X-PHP-Response-Code: 404', true, 404); does work properly under PHP-FPM (FastCGI) header("HTTP/1.1 404 Not Found"); may fail when the protocol is not HTTP/1.1 (i.e. 'HTTP/1.0'). Current protocol must be detected using $_SERVER['SERVER_PROTOCOL'] (available since PHP 4.1.0) There are at least 2 cases when calling http_response_code() result in unexpected behaviour:

When PHP encounter an HTTP response code it does not understand, PHP will replace the code with one it knows from the same group. For example "521 Web server is down" is replaced by "500 Internal Server Error". Many other uncommon response codes from other groups 2xx, 3xx, 4xx are handled this way. On a server with php-fpm and nginx http_response_code() function MAY change the code as expected but not the message. This may result in a strange "404 OK" header for example. This problem is also mentioned on PHP website by a user comment http://www.php.net/manual/en/function.http-response-code.php#112423

这里有HTTP响应状态代码的完整列表供您参考(该列表包括来自IETF互联网标准以及其他IETF rfc的代码。其中许多目前不支持PHP http_response_code函数):http://en.wikipedia.org/wiki/List_of_HTTP_status_codes

你可以通过调用:

http_response_code(521);

如果您有一个自定义客户端应用程序需要额外的HTTP代码,服务器将发送“500 Internal server Error”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响应代码。

新的http_response_code()函数并不能解决所有涉及的问题,反而会引入新的错误。

@dualed提供的“兼容性”解决方案并没有像预期的那样工作,至少在PHP-FPM下是这样。

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

感谢任何测试和评论。

如果你在这里是因为Wordpress在加载环境时给出404错误,这应该可以解决这个问题:

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

该问题是由于它发送一个状态:404 Not Found头。你必须重写它。 这也可以:

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

使用header函数。在第一个参数小节中有一个例子。

在不使用输出缓冲的情况下,在body的任何输出之前添加这一行。

header("HTTP/1.1 200 OK");

将消息部分('OK')替换为适当的消息,并将状态代码替换为适当的代码(404、501等)

如果你的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;
    }