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

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

如何在PHP中做到这一点?

518790 次浏览

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

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

header("HTTP/1.1 200 OK");

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

我刚发现这个问题,觉得需要一个更全面的答案:

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

头函数的第三个参数(PHP >= 4.3)

在使用第一个变体时,显然存在一些问题。我认为最大的问题是,它部分是由PHP或web服务器解析的,并且缺乏文档。

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

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

我推荐第二部。第一个工作在我测试过的所有浏览器上,但一些小的浏览器或网络爬虫可能有一个只包含冒号的标题行问题。头字段名在第二个。变体当然不是标准化的,可以修改,我只是选择了一个描述性的名字。

http_response_code函数(PHP >= 5.4)

http_response_code()函数是在PHP 5.4中引入的,它使很多变得更容易。

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

如果你在这里是因为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");

不幸的是,我发现@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. header("HTTP/1.1 404 Not Found");可能失败时,协议不是HTTP/1.1(即。“HTTP / 1.0”)。当前协议必须使用$_SERVER['SERVER_PROTOCOL']检测(自PHP 4.1.0起可用)

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

  • 当PHP遇到它不理解的HTTP响应代码时,PHP将用它从同一组中知道的代码替换该代码。例如“521 Web服务器宕机”;将被“500个内部服务器错误”所取代。来自其他组的许多其他不常见响应代码2xx、3xx、4xx都是这样处理的。
  • 在带有php-fpm和nginx http_response_code()函数的服务器上,可以按预期更改代码,但不能更改消息。这可能会导致奇怪的“404 ok”;头为例。PHP网站上的一个用户评论http://www.php.net/manual/en/function.http-response-code.php#112423也提到了这个问题

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

你可以通过调用:

http_response_code(521);

服务器将发送“500个内部服务器错误”;如果自定义客户端应用程序需要额外的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响应代码。

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

“compatibility"@dualed提供的解决方案不能像预期的那样工作,至少在PHP-FPM下。

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

感谢任何测试和评论。

header("HTTP/1.1 200 OK");
http_response_code(201);
header("Status: 200 All rosy");
< p > http_response_code (200);由于测试警报404,无法工作 https://developers.google.com/speed/pagespeed/insights/ < / p >

从php5.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

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