PHP:如何发送HTTP响应代码?
我有一个PHP脚本需要HTTP响应代码(状态代码),如HTTP 200 OK,或一些4XX或5XX代码作出响应。
我怎样才能在PHP中做到这一点?
我刚刚发现这个问题,认为需要更全面的回答:
从PHP 5.4开始 ,有三种方法可以实现这一点:
自己组装响应代码(PHP> = 4.0)
header()
函数有一个特殊的用例,用来检测一个HTTP响应行,并让你用自定义的replace它
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 , 原因短语可以是任何自定义string(符合标准),但为了客户端兼容性,我不build议在那里放一个随机string。
注意: php_sapi_name()
需要PHP 4.0.1
头函数的第三个参数(PHP> = 4.3)
使用第一个变体时显然有一些问题。 我认为其中最大的部分是由PHP或Web服务器进行部分parsing,并且logging不完整。
从4.3开始, header
函数有第三个参数,可以让你设置一些响应代码,但是使用它需要第一个参数是一个非空string。 这里有两个选项:
header(':', true, 404); header('X-PHP-Response-Code: 404', true, 404);
我推荐第二个 。 第一个可以在我testing过的所有浏览器上工作,但是一些小的浏览器或者网页爬虫可能会遇到一个只包含冒号的标题行。 第二个标题字段名称。 变体当然没有任何标准化,可以修改,我只是select了一个有希望的描述性名称。
http_response_code函数(PHP> = 5.4)
http_response_code()
函数是在PHP 5.4中引入的,它使事情变得更容易。
http_response_code(404);
就这样。
兼容性
当我需要5.4以下的兼容性时,这里有一个我http_response_code
的函数,但是需要“new” http_response_code
函数的function。 我相信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提供的解决scheme存在各种缺陷。
-
使用
substr($sapi_type, 0, 3) == 'cgi'
不是enogh来检测快速CGI。 当使用PHP-FPM FastCGI进程pipe理器时,php_sapi_name()
返回fpm不是cgi -
Fasctcgi和php-fpm暴露了@Josh提到的另一个错误 – 使用
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()
时,至less有两种情况会导致意外的行为:- 当PHP遇到一个HTTP响应代码,它不明白,PHP将代替一个它从同一组中知道的代码。 例如“521 Web服务器closures”被replace为“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://en.wikipedia .ORG /维基/ List_of_HTTP_status_codes
您可以通过调用以下方式轻松testing此错误
http_response_code(521);
如果您有一个自定义客户端应用程序调用您的服务器并期待一些额外的HTTP代码,服务器将发送“500内部服务器错误”HTTP响应代码,导致意外错误。
我的解决scheme(对于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提供的“兼容性”解决scheme不能按预期工作,至less在PHP-FPM下是如此。
@dualed提供的其他解决scheme也有不同的错误。 快速CGI检测不处理PHP-FPM。 必须检测当前的协议。
任何testing和意见表示赞赏。
在没有使用输出缓冲的情况下,在主体的任何输出之前添加此行。
header("HTTP/1.1 200 OK");
将消息部分('OK')replace为适当的消息,并将状态代码replace为适当的代码(404,501等)
使用标题function。 在第一个参数部分有一个例子。
如果你在这里是因为Wordpress在加载环境的时候给了404的话,这应该解决这个问题:
define('WP_USE_THEMES', false); require('../wp-blog-header.php'); status_header( 200 ); //$wp_query->is_404=false; // if necessary
问题是由于它发送状态:404未find标题。 你必须重写。 这也将工作:
define('WP_USE_THEMES', false); require('../wp-blog-header.php'); header("HTTP/1.1 200 OK"); header("Status: 200 All rosy");
header("HTTP/1.1 200 OK"); http_response_code(201);
http_response_code(200); 不工作,因为testing警报404 https://developers.google.com/speed/pagespeed/insights/
从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