如何让 php 在遇到致命异常时返回 500?

发布于 2024-08-07 23:48:25 字数 61 浏览 7 评论 0原文

PHP 致命错误以状态代码 200 返回 HTTP 客户端。如何让它返回状态代码 500(内部服务器错误)?

PHP fatal errors come back as status code 200 to the HTTP client. How can I make it return a status code 500 (Internal server error)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

如日中天 2024-08-14 23:48:25
header("HTTP/1.1 500 Internal Server Error");

另请参阅此回答

header("HTTP/1.1 500 Internal Server Error");

Also, see this answer

眸中客 2024-08-14 23:48:25

这正是我昨天遇到的问题,我找到了解决方案如下:

  1. 首先,您需要捕获 PHP 致命错误,这是错误类型 E_ERROR。当此错误发生时,脚本将存储错误并终止执行。您可以通过调用函数error_get_last()来获取存储的错误。

  2. 在脚本终止之前,总会调用回调函数register_shutdown_function()。因此,您需要通过此函数注册一个错误处理程序来执行您想要的操作,在本例中,返回标头 500 和自定义的内部错误页面(可选)。

    函数 my_error_handler()
    {
    $last_error = error_get_last();
    if ($last_error && $last_error['type']==E_ERROR)
    {
    header("HTTP/1.1 500 内部服务器错误");
    echo '...';//500页的html
    }
    }
    register_shutdown_function('my_error_handler');

注意:如果要捕获以E_USER*开头的自定义错误类型,可以使用函数set_error_handler()注册错误处理程序并通过函数trigger_error触发错误,但是该错误处理程序无法处理E_ERROR错误类型。请参阅 php.net 上有关 错误处理程序 的说明

This is exactly the problem I had yesterday and I found solution as follows:

  1. first of all, you need to catch PHP fatal errors, which is error type E_ERROR. when this error occurs, script will be stored the error and terminate execution. you can get the stored error by calling function error_get_last().

  2. before script terminated, a callback function register_shutdown_function() will always be called. so you need to register a error handler by this function to do what you want, in this case, return header 500 and a customized internal error page (optional).

    function my_error_handler()
    {
    $last_error = error_get_last();
    if ($last_error && $last_error['type']==E_ERROR)
    {
    header("HTTP/1.1 500 Internal Server Error");
    echo '...';//html for 500 page
    }
    }
    register_shutdown_function('my_error_handler');

Note: if you want to catch custom error type, which start with E_USER*, you can use function set_error_handler() to register error handler and trigger error by function trigger_error, however, this error handler can not handle E_ERROR error type. see explanation on php.net about error handler

ㄖ落Θ余辉 2024-08-14 23:48:25

标准 PHP 配置确实在发生错误时返回 500!只需确保您的 display_errors = 关闭即可。您可以通过以下方式模拟它:

ini_set('display_errors', 0); 
noFunction();

在生产中,默认情况下,display_errors 指令处于关闭状态。

Standard PHP configuration does return 500 when error occurs! Just make sure that your display_errors = off. You can simulate it with:

ini_set('display_errors', 0); 
noFunction();

On production display_errors directive is off by default.

仙气飘飘 2024-08-14 23:48:25

由于 PHP >= 5.4

http_response_code(500);
echo json_encode( [ 'success' => false , 'message' => 'Crazy thing just happened!' ]);
exit();

请在 echo 之前设置 httpCode。

Since PHP >= 5.4

http_response_code(500);
echo json_encode( [ 'success' => false , 'message' => 'Crazy thing just happened!' ]);
exit();

Please set the httpCode before echo.

蓝眼睛不忧郁 2024-08-14 23:48:25

我使用“set_exception_handler”来处理未捕获的异常。

function handleException($ex) {
      error_log("Uncaught exception class=" . get_class($ex) . " message=" . $ex->getMessage() . " line=" . $ex->getLine());
      ob_end_clean(); # try to purge content sent so far
      header('HTTP/1.1 500 Internal Server Error');
      echo 'Internal error';
    }

set_exception_handler('handleException');

I have used "set_exception_handler" to handle uncaught exceptions.

function handleException($ex) {
      error_log("Uncaught exception class=" . get_class($ex) . " message=" . $ex->getMessage() . " line=" . $ex->getLine());
      ob_end_clean(); # try to purge content sent so far
      header('HTTP/1.1 500 Internal Server Error');
      echo 'Internal error';
    }

set_exception_handler('handleException');
千鲤 2024-08-14 23:48:25

根据 PHP 文档,不可能以任何方式处理 PHP E_ERROR:
http://www.php.net/manual/en/ function.set-error-handler.php

根据该链接,也无法处理“E_PARSE、E_CORE_ERROR、E_CORE_WARNING、E_COMPILE_ERROR、E_COMPILE_WARNING 和大部分 E_STRICT”。

您可以为其他错误、警告和通知(包括 E_USER_ERROR)提供处理程序,但这实际上并不像听起来那么有用,因为该错误只是由程序员使用trigger_error() 故意抛出的。

当然,您可以捕获任何异常(甚至是本机 PHP 函数抛出的异常)。

我同意这是一个问题。当应用程序代码崩溃并烧毁时,服务器不应返回 200 OK。

It is not possible to handle PHP E_ERROR in any way according to the PHP documentation:
http://www.php.net/manual/en/function.set-error-handler.php

Nor is is possible to handle "E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT" according to that link.

You CAN provide a handler for the other error, warning, and notices including E_USER_ERROR, but that's really not as useful as it sounds since this error only gets thrown intentionally by the programmer with trigger_error().

And of course you can catch any Exception (even the ones thrown by the native PHP functions).

I agree that this is a problem. Servers should NOT return 200 OK when application code crashes and burns.

地狱即天堂 2024-08-14 23:48:25

您必须使用 try/catch 捕获抛出的错误,然后使用它catch 块发送带有 500 错误的 header()

try {
    ...badcode...
    throw new Exception('error');

} catch (Exception $e) {

    header("Status: 500 Server Error");
    var_dump($e->getMessage());
}

如果致命异常没有被 try {} catch 块包围,那么您必须注册一个全局处理程序并使用 register_shutdown_function() 在脚本末尾检查错误。

You would have to catch the thrown error using try/catch and then use that catch block to send a header() with the 500 error.

try {
    ...badcode...
    throw new Exception('error');

} catch (Exception $e) {

    header("Status: 500 Server Error");
    var_dump($e->getMessage());
}

If the fatal exception is not surrounded by try {} catch blocks then you must register a global handler and use register_shutdown_function() to check for an error at script end.

吻安 2024-08-14 23:48:25

永远不要忘记将 header("HTTP/1.1 200 OK", true, 200); 设置为任何执行路径的最后一行:

//first things first:
header("HTTP/1.1 500 Internal Server Error", true, 500);


//Application code, includes, requires, etc. [...]


//somewhere something happens
//die();
throw new Exception("Uncaught exception!");


//last things last, only reached if code execution was not stopped by uncaught exception or some fatal error
header("HTTP/1.1 200 OK", true, 200);

PHP 5.4 中,您可以替换 <上面的 code>header 函数具有更好的 http_response_code(200)<代码>http_response_code(500)

Never forget to set header("HTTP/1.1 200 OK", true, 200); as the last line of any execution path:

//first things first:
header("HTTP/1.1 500 Internal Server Error", true, 500);


//Application code, includes, requires, etc. [...]


//somewhere something happens
//die();
throw new Exception("Uncaught exception!");


//last things last, only reached if code execution was not stopped by uncaught exception or some fatal error
header("HTTP/1.1 200 OK", true, 200);

In PHP 5.4 you can replace the header function above with the much better http_response_code(200) or http_response_code(500).

时间海 2024-08-14 23:48:25

处理致命错误(编译错误,例如缺少分号)时最困难的事情是脚本不会被执行,因此在该脚本中设置状态代码无济于事。但是,当您包含或需要脚本时,无论包含的脚本中是否存在错误,都将执行调用脚本。有了这个,我得出了这个解决方案:

rock-solid-script.php:

// minimize changes to this script to keep it rock-solid
http_response_code(500); // PHP >= 5.4
require_once("script-i-want-to-guard-for-errors.php");

script-i-want-to-guard-for-errors.php:

// do all the processsing
// don't produce any output
// you might want to use output buffering

http_response_code(200); // PHP >= 5.4

// here you can produce the output

Direct your call to the rock-solid-script.php 就准备好了去。

我希望最好将 .htaccess 中的默认状态代码设置为 500。这对我来说似乎更优雅,但我找不到一种方法来实现它。我尝试了 RewriteRule R 标志,但这完全阻止了 php 的执行,所以没有用。

The hard thing when dealing with fatal errors (compile errors, for example a missing semicolon) is that the script won't be executed, so it won't help to set the status code in that script. However, when you include or require a script, the calling script will be executed, regardless of errors in the included script. With this, I come to this solution:

rock-solid-script.php:

// minimize changes to this script to keep it rock-solid
http_response_code(500); // PHP >= 5.4
require_once("script-i-want-to-guard-for-errors.php");

script-i-want-to-guard-for-errors.php:

// do all the processsing
// don't produce any output
// you might want to use output buffering

http_response_code(200); // PHP >= 5.4

// here you can produce the output

Direct your call to the rock-solid-script.php and you're ready to go.

I would have liked it better to set the default status code to 500 in .htaccess. That seems more elegant to me but I can't find a way to pull it off. I tried the RewriteRule R-flag, but this prevents execution of php altogether, so that's no use.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文