Apache / PHP在错误页面上返回HTTP状态代码200

时间:2015-03-10 19:55:25

标签: php apache error-code

我在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:on
  • display_startup_errors:on
  • error_reporting:-1(这会导致报告所有错误)

3 个答案:

答案 0 :(得分:13)

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

  

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

     

需要关闭显示错误的原因是因为显示的错误会生成输出,并且输出会导致标头被发送出去。我担心我们对此无能为力。

所以问题的答案是:

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

答案 1 :(得分:1)

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

package com.github.fcopardo.room.base

import android.arch.persistence.room.Delete
import android.arch.persistence.room.Insert
import android.arch.persistence.room.OnConflictStrategy
import android.arch.persistence.room.Update
import android.content.Context
import java.io.File

abstract class LimitedDao<T> {

    private var byteLimit : Long = 0
    private var context : Context? = null
    private var databaseName : String = ""

    public fun setByteLimit(byteLimit : Long){
        this.byteLimit = byteLimit
    }

    public fun setContext(context: Context?){
        this.context = context
    }

    public fun setDatabaseName(databaseName: String){
        this.databaseName = databaseName
    }

    protected fun writingCondition() : Boolean {
        var result = true

        if(byteLimit>0){
            var dbFile : File? = context?.getDatabasePath(databaseName)

            if(dbFile!=null){
                result = dbFile.length() >byteLimit
            }
        }

        return result
    }

    @Insert
    protected abstract fun insert(data: T)

    public fun insertData(data:T){
        if(writingCondition()) insert(data)
    }

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    protected abstract fun persist(data: T)

    public fun persistData(data:T){
        if(writingCondition()) persist(data)
    }

    @Delete
    protected abstract fun delete(data: T)

    @Delete
    protected abstract fun delete(data: List<T>)

    @Update
    protected abstract fun update(data: T)

    @Update
    protected abstract fun update(data: List<T>)
}

如果# 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'; 中发生崩溃错误,通过自动添加文件设置的500仍将执行。但是,除非打开index.php和/或display_error,否则不会有任何输出。如果display_startup_error或其任何依赖项发生崩溃错误,则关闭功能将处理这些错误。

这里仍然存在需要考虑的场景:

  • 应输出什么格式?检查ACCEPT标头或相应的默认值。
  • 如果输出已经开始怎么办?您如何中断流以发出信号到侧面?

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

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

答案 2 :(得分:0)

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