我有一个PHP脚本,需要使用HTTP响应代码(状态代码)做出响应,如HTTP 200 OK,或一些4XX或5XX代码。
如何在PHP中做到这一点?
使用头函数。在第一个参数小节中有一个例子。
在不使用输出缓冲的情况下,在body的任何输出之前添加这一行。
header("HTTP/1.1 200 OK");
将消息部分('OK')替换为适当的消息,并将状态代码替换为适当的代码(404、501等)
我刚发现这个问题,觉得需要一个更全面的答案:
从PHP 5.4开始,有三种方法可以完成这个任务:
header()函数有一个特殊的用例,它检测HTTP响应行,并让你用自定义的响应行替换它
header()
但是,这需要对(快速)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_sapi_name()
在使用第一个变体时,显然存在一些问题。我认为最大的问题是,它部分是由PHP或web服务器解析的,并且缺乏文档。
从4.3开始,header函数有第3个参数,可以让你轻松地设置响应代码,但使用它需要第一个参数是非空字符串。这里有两种选择:
header
header(':', true, 404); header('X-PHP-Response-Code: 404', true, 404);
我推荐第二部。第一个做工作在我测试过的所有浏览器上,但一些小的浏览器或网络爬虫可能有一个只包含冒号的标题行问题。头字段名在第二个。变体当然不是标准化的,可以修改,我只是选择了一个描述性的名字。
http_response_code()函数是在PHP 5.4中引入的,它使很多变得更容易。
http_response_code()
http_response_code(404);
这是所有。
这里是一个函数,当我需要5.4以下的兼容性,但想要“新”http_response_code函数的功能时,我已经准备好了。我相信PHP 4.3的向后兼容性已经足够了,但是你永远不知道…
http_response_code
// 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
define('WP_USE_THEMES', false); require('../wp-blog-header.php'); header("HTTP/1.1 200 OK"); header("Status: 200 All rosy");
不幸的是,我发现@dualed提出的解决方案有各种缺陷。
使用substr($sapi_type, 0, 3) == 'cgi'不足以检测快速CGI。当使用PHP-FPM FastCGI进程管理器时,php_sapi_name()返回fpm而不是cgi
substr($sapi_type, 0, 3) == 'cgi'
Fasctcgi和php-fpm暴露了@Josh提到的另一个错误-使用header('X-PHP-Response-Code: 404', true, 404);在php-fpm (FastCGI)下正常工作
header('X-PHP-Response-Code: 404', true, 404);
header("HTTP/1.1 404 Not Found");可能失败时,协议不是HTTP/1.1(即。“HTTP / 1.0”)。当前协议必须使用$_SERVER['SERVER_PROTOCOL']检测(自PHP 4.1.0起可用)
header("HTTP/1.1 404 Not Found");
$_SERVER['SERVER_PROTOCOL']
这里有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");
从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中的文档:
如果你的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; }