【问题标题】:Apache/PHP returns HTTP Status Code 200 on error pagesApache/PHP 在错误页面上返回 HTTP 状态代码 200
【发布时间】:2015-05-12 10:26:06
【问题描述】:

我在 CentOS 7 上运行 PHP 5.4,当 php 文件抛出错误(异常或语法错误)时,它返回 HTTP 200 状态代码而不是 500。

当 PHP 遇到错误时如何让它返回 500 服务器错误?

我已经尝试查看其他 Stackoverflow 帖子,它们似乎都指向有关返回您自己的 500 错误代码的解决方案(我认为这应该是 PHP 本身的正常行为,而无需我手动触发 http标头,根据此信息:PHP emitting 500 on errors - where is this documented?) 它还指出 Xdebug 是一个可能的问题,但即使我在没有 Xdebug 的情况下重建服务器,我的问题仍然存在。

我的相关设置是:

  • display_errors:开启
  • display_startup_errors:开启
  • error_reporting: -1(这会导致报告所有错误)

【问题讨论】:

  • 您为什么要这样做? Apache 错误和 php 错误不是一回事
  • 但他可能会以 PHP 自动响应 500 的方式处理任何 PHP 端异常。
  • @Dagon 我说的是 apache 提供的 http 状态码。我正在尝试获取 PHP 错误触发 500 状态代码的行为。
  • 是的,但为什么呢?似乎是个糟糕的主意
  • @Dagon 你能解释一下为什么你认为这很糟糕吗? 500 个状态码意味着什么,就像 200 个一样。返回 200 的损坏页面在调试过程中没有多大帮助,而且我们也不希望搜索引擎在应用暂时出错时索引错误页面文本。

标签: php apache error-code


【解决方案1】:

根据a PHP bug report,这里描述的行为是由于 display_errors 是如何设置的。

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

之所以需要关闭显示错误,是因为显示错误产生输出,输出导致headers被发送出去。恐怕我们对此无能为力。

所以问题的答案是:

  • 当 display_errors 开启时,它将始终返回 200。
  • 当 display_errors 关闭时,它将返回 500。

【讨论】:

  • 上个月有人发布了关于该错误的拉取请求。也许我们需要让 php 开发社区获得批准。
【解决方案2】:

请注意,这有时可能归结为 apache 中的 CustomLog 格式。例如,%>s(“最终状态”)可以(正确地)在访问日志中产生 403,而即使响应的状态代码是其他内容,%s 也可能会记录 200。

【讨论】:

    【解决方案3】:

    解决错误 #50921:使用 auto_prepend_file 将 http 响应代码设置为 500,然后在您知道页面已引导时将其设置为 200。一个有代表性但不全面的例子:

    # 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';
    

    如果index.php 中有崩溃错误,通过自动前置文件设置的 500 仍将执行。不过,除非display_error 和/或display_startup_error 打开,否则不会有任何输出。如果bootstrap.php 或其任何依赖项出现崩溃错误,则关闭函数将处理这些错误。

    这里还有场景,需要考虑:

    • 应该输出什么格式?检查 ACCEPT 标头,或相应地默认。
    • 如果输出已经开始怎么办?您如何打断直播以表明有什么事情发生了?

    这在很大程度上取决于您对环境的控制程度(例如,写入 INI_SYSTEM 级别的配置)以及您的框架如何运行(例如,ob_start 或否)。

    我会强调这只是一个解决方法。如果您的 auto_prepend_file 本身有解析错误,那么您将回到第一方:PHP 发出 200 状态错误代码。修复引擎以发出 500 是打破这种先有鸡还是先有蛋的循环的唯一正确方法。

    【讨论】:

      猜你喜欢
      • 2011-03-16
      • 2011-11-18
      • 1970-01-01
      • 2021-04-25
      • 1970-01-01
      • 2017-07-12
      • 2012-07-31
      • 2016-04-16
      • 2012-06-18
      相关资源
      最近更新 更多