问题
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.
How can I do this in PHP?
回答1:
I just found this question and thought it needs a more comprehensive answer:
As of PHP 5.4 there are three methods to accomplish this:
Assembling the response code on your own (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/1.1 200 OK");
However, this requires special treatment for (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 phrase can be any custom string (that conforms to the standard), but for the sake of client compatibility I do not recommend putting a random string there.
Note: php_sapi_name() requires PHP 4.0.1
3rd argument to header function (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.
Since 4.3, the header
function 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:
header(':', true, 404);
header('X-PHP-Response-Code: 404', true, 404);
I recommend the 2nd one. The first does work 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.
http_response_code function (PHP >= 5.4)
The http_response_code() function was introduced in PHP 5.4, and it made things a lot easier.
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_code
function. I believe PHP 4.3 is more than enough backwards compatibility, but you never know...
// 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;
}
}
回答2:
Unfortunately I found solutions presented by @dualed have various flaws.
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 cgiFasctcgi 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)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.0There 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
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
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.
My solution (for all PHP versions since 4.1.0):
$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.
The new http_response_code() function does not solve all the problems involved but make things worst introducing new bugs.
The "compatibility" solution offered by @dualed does not work as expected, at least under 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.
Any tests and comments are appreciated.
回答3:
since PHP 5.4 you can use http_response_code()
for get and set header status 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:
http_response_code
回答4:
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)
回答5:
If you are here because of Wordpress giving 404's when loading the environment, this should fix the problem:
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:
define('WP_USE_THEMES', false);
require('../wp-blog-header.php');
header("HTTP/1.1 200 OK");
header("Status: 200 All rosy");
回答6:
With the header function. There is an example in the section on the first parameter it takes.
回答7:
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/
回答8:
We can get different return value from http_response_code via the two different environment:
- Web Server Environment
- CLI environment
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).
At CLI Environment, true will be return if you provided a response code and false if you do not provide any response_code.
Example of Web Server Environment of Response_code's return value:
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:
var_dump(http_response_code()); // bool(false)
var_dump(http_response_code(501)); // bool(true)
var_dump(http_response_code()); // int(501)
来源:https://stackoverflow.com/questions/3258634/php-how-to-send-http-response-code