Apache/PHP returns HTTP Status Code 200 on error pages

前端 未结 3 1103
囚心锁ツ
囚心锁ツ 2021-02-14 21:33

I\'m running PHP 5.4 on CentOS 7 and when there is a php file that throws an error (either an exception, or a syntax error) it returns an HTTP 200 status code instead of 500.

相关标签:
3条回答
  • 2021-02-14 22:00

    A work around to bug #50921: use auto_prepend_file to set the http response code to 500, then set it to 200 when you know the page has bootstrapped. A representative, but not comprehensive, example:

    # php.ini
    auto_prepend_file = /path/to/auto_prepend_file.php
    
    # auto_prepend_file.php
    <?php http_response_code(500);
    
    # index.php
    <?php
    register_shutdown_function(function () {
        $error = error_get_last();
        switch ($error['type'] ?? 0) {
        case E_ERROR:                                                         
        case E_PARSE:                                                         
        case E_CORE_ERROR:                                                    
        case E_COMPILE_ERROR:                                                 
        case E_RECOVERABLE_ERROR:                                             
            file_put_contents('/path/to/log', $error['message'], FILE_APPEND);
            http_response_code(500);
            echo 'Something went horribly wrong.';
            echo str_repeat(' ', 512);
            break;
    });
    
    http_response_code(200);
    require_once '/path/to/bootstrap.php';
    

    If index.php has a crashing error in it, the 500 set via auto-prepend file will still execute. There won't be any output unless display_error and/or display_startup_error are on, though. If bootstrap.php or any of its dependents have crashing error, then the shutdown function will handle those.

    There are still scenarios here, which need to be considered:

    • What format should be output? Check ACCEPT header, or default accordingly.
    • What if output has already been started? How do you interrupt the stream to signal something went sideways?

    A lot of this depends upon how much control you have over your environment (eg, write to INI_SYSTEM level config) and how your framework operates (eg ob_start, or no).

    I'll emphasize this is just a workaround. If your auto_prepend_file itself has parse errors, then you're back to square one: PHP emits a 200 status error code. Fixing the engine to emit a 500 is the only proper way to break this chicken-and-egg cycle.

    0 讨论(0)
  • 2021-02-14 22:12

    According to a PHP bug report, the behavior described here is due to how display_errors is set.

    [2010-02-03 19:03 UTC] derick@php.net

    The reason why display errors needs to be turned of, is because displayed errors generate output, and output causes the headers to be send out. I'm afraid we can't do much about this.

    So the answer to the question is that:

    • When display_errors is on it will return 200 always.
    • When display_errors is off it will return 500.
    0 讨论(0)
  • 2021-02-14 22:18

    Note that this may sometimes be down to the CustomLog format in apache. For example %>s ("the final status") can (correctly) yield a 403 in the access log whereas just %s may record a 200 even when the status code of the response was something else.

    0 讨论(0)
提交回复
热议问题