PHP: How to send HTTP response code?

后端 未结 9 1834
无人共我
无人共我 2020-11-22 06:05

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?

相关标签:
9条回答
  • 2020-11-22 06:26

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

    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

    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.

    0 讨论(0)
  • 2020-11-22 06:28

    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)

    0 讨论(0)
  • 2020-11-22 06:32

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

    1. Web Server Environment
    2. 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)
    
    0 讨论(0)
提交回复
热议问题