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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3258634/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 09:09:22  来源:igfitidea点击:

PHP: How to send HTTP response code?

phphttp-response-codes

提问by Paulo Coghi - Reinstate Monica

I have a PHP script that needs to make responses with HTTP response codes (status-codes), like HTTP 200 OK, or some 4XX or 5XX code.

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

How can I do this in PHP?

我怎样才能在 PHP 中做到这一点?

回答by dualed

I just found this question and thought it needs a more comprehensive answer:

我刚刚发现了这个问题,并认为它需要一个更全面的答案:

As of PHP 5.4there are three methods to accomplish this:

PHP 5.4 开始,有三种方法可以实现这一点:

Assembling the response code on your own (PHP >= 4.0)

自行组装响应代码(PHP >= 4.0)

The header()function has a special use-case that detects a HTTP response line and lets you replace that with a custom one

header()函数有一个特殊用例,可以检测 HTTP 响应行并让您用自定义响应行替换它

header("HTTP/1.1 200 OK");

However, this requires special treatment for (Fast)CGI PHP:

但是,这需要对 (Fast)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");

Note:According to the HTTP RFC, the reason phrasecan be any custom string (that conforms to the standard), but for the sake of client compatibility I do notrecommend putting a random string there.

注意:根据HTTP RFC原因短语可以是任何自定义字符串(符合标准),但为了客户端兼容性,我建议在那里放置随机字符串。

Note:php_sapi_name()requires PHP 4.0.1

注意:php_sapi_name()需要PHP 4.0.1

3rd argument to header function (PHP >= 4.3)

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

There are obviously a few problems when using that first variant. The biggest of which I think is that it is partly parsed by PHP or the web server and poorly documented.

使用第一个变体时显然存在一些问题。我认为其中最大的一个问题是它被 PHP 或 Web 服务器部分解析,并且文档记录不足。

Since 4.3, the headerfunction has a 3rd argument that lets you set the response code somewhat comfortably, but using it requires the first argument to be a non-empty string. Here are two options:

从 4.3 开始,该header函数具有第三个参数,可以让您稍微轻松地设置响应代码,但使用它需要第一个参数是非空字符串。这里有两个选项:

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

I recommend the 2nd one. The first doeswork on all browsers I have tested, but some minor browsers or web crawlers may have a problem with a header line that only contains a colon. The header field name in the 2nd. variant is of course not standardized in any way and could be modified, I just chose a hopefully descriptive name.

我推荐第二个。第一个确实适用于我测试过的所有浏览器,但一些较小的浏览器或网络爬虫可能会遇到标题行仅包含冒号的问题。标题字段名称在 2 中。变体当然没有以任何方式标准化并且可以修改,我只是选择了一个有希望的描述性名称。

http_response_code function (PHP >= 5.4)

http_response_code 函数(PHP >= 5.4)

The http_response_code()function was introduced in PHP 5.4, and it made things a loteasier.

http_response_code()函数在PHP 5.4引入的,它使事情很多更容易。

http_response_code(404);

That's all.

就这样。

Compatibility

兼容性

Here is a function that I have cooked up when I needed compatibility below 5.4 but wanted the functionality of the "new" http_response_codefunction. I believe PHP 4.3 is more than enough backwards compatibility, but you never know...

这是我在需要低于 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;
    }
}

回答by Grigore Madalin

Unfortunately I found solutions presented by @dualed have various flaws.

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

  1. 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

  2. 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)

  3. 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

  4. 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
  1. 使用substr($sapi_type, 0, 3) == 'cgi'不足以检测快速 CGI。使用 PHP-FPM FastCGI Process Manager 时,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

For your reference here there is the full list of HTTP response status codes (this list includes codes from IETF internet standards as well as other IETF RFCs. Many of them are NOT currently supported by PHP http_response_code function): http://en.wikipedia.org/wiki/List_of_HTTP_status_codes

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

You can easily test this bug by calling:

您可以通过调用轻松测试此错误:

http_response_code(521);

The server will send "500 Internal Server Error" HTTP response code resulting in unexpected errors if you have for example a custom client application calling your server and expecting some additional HTTP codes.

服务器将发送“500 Internal Server Error”HTTP 响应代码,导致意外错误,例如,如果您有一个自定义客户端应用程序调用您的服务器并期待一些额外的 HTTP 代码。



My solution (for all PHP versions since 4.1.0):

我的解决方案(适用于 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);
}


Conclusion

结论

http_response_code() implementation does not support all HTTP response codes and may overwrite the specified HTTP response code with another one from the same group.

http_response_code() 实现不支持所有 HTTP 响应代码,并且可能会用来自同一组的另一个响应代码覆盖指定的 HTTP 响应代码。

The new http_response_code() function does not solve all the problems involved but make things worst introducing new bugs.

新的 http_response_code() 函数并没有解决所有涉及的问题,而是让事情变得更糟,引入了新的错误。

The "compatibility" solution offered by @dualed does not work as expected, at least under PHP-FPM.

@dualed 提供的“兼容性”解决方案无法按预期工作,至少在 PHP-FPM 下是这样。

The other solutions offered by @dualed also have various bugs. Fast CGI detection does not handle PHP-FPM. Current protocol must be detected.

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

Any tests and comments are appreciated.

任何测试和评论表示赞赏。

回答by Seyed Ali Roshan

since PHP 5.4 you can use http_response_code()for get and set header status code.

自 PHP 5.4 起,您可以http_response_code()用于获取和设置标头状态代码。

here an example:

这里有一个例子:

<?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());
?>

here is the document of this function in php.net:

这是这个函数在 php.net 中的文档:

http_response_code

http_response_code

回答by sparkey0

Add this line before any output of the body, in the event you aren't using output buffering.

如果您不使用输出缓冲,请在正文的任何​​输出之前添加此行。

header("HTTP/1.1 200 OK");

Replace the message portion ('OK') with the appropriate message, and the status code with your code as appropriate (404, 501, etc)

将消息部分(“OK”)替换为适当的消息,并根据需要将状态代码替换为您的代码(404、501 等)

回答by jaggedsoft

If you are here because of Wordpress giving 404's when loading the environment, this should fix the problem:

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

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

The problem is due to it sending a Status: 404 Not Found header. You have to override that. This will also work:

问题是由于它发送了一个 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");

回答by Quentin

With the headerfunction. There is an example in the section on the first parameter it takes.

标题功能。在它采用的第一个参数的部分中有一个示例。

回答by alpc

header("HTTP/1.1 200 OK");
http_response_code(201);
header("Status: 200 All rosy");

http_response_code(200); not work because test alert 404 https://developers.google.com/speed/pagespeed/insights/

http_response_code(200); 不起作用,因为测试警报 404 https://developers.google.com/speed/pagespeed/insights/

回答by Abdo-Host

If your version of PHP does not include this function:

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

回答by GaziAnis

We can get different return value from http_response_code via the two different environment:

我们可以通过两种不同的环境从 http_response_code 得到不同的返回值:

  1. Web Server Environment
  2. CLI environment
  1. 网络服务器环境
  2. 命令行环境

At the web server environment, return previous response code if you provided a response code or when you do not provide any response code then it will be print the current value. Default value is 200 (OK).

在 web 服务器环境中,如果您提供了响应代码,或者当您不提供任何响应代码时,则返回先前的响应代码,则将打印当前值。默认值为 200(确定)。

At CLI Environment, true will be return if you provided a response code and false if you do not provide any response_code.

在 CLI 环境中,如果您提供了响应代码,则返回 true,如果您不提供任何 response_code,则返回 false。

Example of Web Server Environment of Response_code's return value:

Response_code 返回值的 Web 服务器环境示例:

var_dump(http_respone_code(500)); // int(200)
var_dump(http_response_code()); // int(500)

Example of CLI Environment of Response_code's return value:

Response_code 返回值的 CLI 环境示例:

var_dump(http_response_code()); // bool(false)
var_dump(http_response_code(501)); // bool(true)
var_dump(http_response_code()); // int(501)