我有一个PHP脚本需要使用HTTP响应代码(状态代码)进行响应,如HTTP 200 OK或某些4XX或5XX代码.
我怎么能用PHP做到这一点?
我刚发现这个问题并认为它需要一个更全面的答案:
从PHP 5.4开始,有三种方法可以实现此目的:
该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或Web服务器部分解析而且文档记录不足.
从4.3开始,该header
函数有一个第三个参数,可以让你轻松地设置响应代码,但使用它需要第一个参数为非空字符串.这有两个选择:
header(':', true, 404); header('X-PHP-Response-Code: 404', true, 404);
我推荐第二个.第一不上我已经测试了所有的浏览器,但一些小的浏览器或网络爬虫可能有只包含一个冒号标题行的问题.第2个中的标题字段名称.变体当然没有以任何方式标准化并且可以修改,我只是选择了一个有希望的描述性名称.
该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; } }
不幸的是,我发现@dualed提出的解决方案存在各种缺陷.
使用substr($sapi_type, 0, 3) == 'cgi'
不能确定快速CGI.使用PHP-FPM FastCGI Process Manager时,php_sapi_name()
返回fpm而不是cgi
Fasctcgi和php-fpm暴露了@Josh提到的另一个bug - 使用header('X-PHP-Response-Code: 404', true, 404);
在PHP-FPM(FastCGI)下正常工作
header("HTTP/1.1 404 Not Found");
协议不是HTTP/1.1(即'HTTP/1.0')时可能会失败.必须使用$_SERVER['SERVER_PROTOCOL']
(从PHP 4.1.0开始提供)检测当前协议
调用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目前不支持PHP http_response_code函数):http://en.wikipedia .ORG /维基/ List_of_HTTP_status_codes
您可以通过调用以下命令轻松测试此错误
http_response_code(521);
如果您有一个自定义客户端应用程序调用您的服务器并期望一些额外的HTTP代码,服务器将发送"500内部服务器错误"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()函数并没有解决所有涉及的问题,但是最糟糕的是引入了新的错误.
@dualed提供的"兼容性"解决方案无法按预期工作,至少在PHP-FPM下.
@dualed提供的其他解决方案也存在各种错误.快速CGI检测不能处理PHP-FPM.必须检测当前协议.
任何测试和评论都表示赞赏.
从PHP 5.4开始,您可以使用http_response_code()
get和set头状态代码.
这里有一个例子:
这是php.net中此函数的文档:
http_response_code
如果您没有使用输出缓冲,请在正文的任何输出之前添加此行.
header("HTTP/1.1 200 OK");
将消息部分("确定")替换为相应的消息,并使用适当的代码替换状态代码(404,501等)
如果你在这里是因为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");
具有头功能.它的第一个参数部分有一个例子.