2010-02-25 116 views
14

我有一个启用了restful的web服务站点,所以其他网站/ ajax脚本可以拨打该站点来获取/设置数据。但是,每当Web服务站点以某种方式返回一个PHP致命错误时,返回的HTTP状态是200而不是500.是否有解决此问题的方法,以便每当发生致命错误时返回500而不是200?或者,如果不可能,我如何更改我的客户端以识别Web服务返回的致命错误?Catch PHP致命错误

+0

相关http://stackoverflow.com/questions/3052715/php-how-to-return-an-http-500-code-on-any-error-no-matter-what – cweiske 2011-04-14 11:48:03

回答

13

一种可能的方式是设置默认响应500,如果一切执行成功设置响应200:

http_response_code(500); 
render_my_page(); 
http_response_code(200); 
+7

抛出一个大页面缓冲区,以防止关于输出的臭名昭着的错误已经开始,应该这样做。 – TheJacobTaylor 2010-02-25 04:28:24

+1

这个,或者确保你把'<?php头('500 Internal Server Error'); ?>'在脚本的开头,而不是在棘手的部分之前。 – 2010-06-06 12:46:28

+3

还有一个PHP功能请求打开:http://bugs.php.net/bug.php?id=50921 – cweiske 2011-04-14 11:46:48

3

创建自定义错误处理程序(set_error_handler)并致电header("HTTP/1.0 500 Service not available");

编辑:

每第一个评论我的答案,你不能捕获真正的致命错误。但是,如果输出缓冲被禁用并且错误未显示在屏幕上,PHP将默认设置致命错误的500错误代码。

<?php 
     $x = y(); 
?> 

上面的代码将返回一个500错误代码,如果没有发送到屏幕。

所以,如果你想这样的错误设置适当的代码,做自己的缓冲:

<?php 
     $buffer = 'blah'; 
     $x = y(); // will trigger 500 error 
     echo $buffer; 
?> 
+9

自定义错误处理程序可以' t捕获致命错误(例如,调用非对象上的方法;耗尽时间限制/内存限制)或解析错误。从文档:'以下错误类型不能用用户定义的函数处理:E_ERROR,E_PARSE,E_CORE_ERROR,E_CORE_WARNING,E_COMPILE_ERROR,E_COMPILE_WARNING' http://php.net/set_error_handler – 2010-02-25 04:27:19

+0

是的,值得一提。我没有假设他的字面意思是致命的,因为有些人用它来表示任何不能从中恢复的错误。 – Matthew 2010-02-25 04:44:43

+0

:D我真的意味着致命的错误XD – Jeffrey04 2010-02-25 08:16:55

-5

我会认为你想赶上和部署应用程序之前解决所有致命的错误,因为很多都是代码中的错误,遗漏包括,不存在的物体,这些都是发展错误。即使是内存节约的编码技术,也可以最大程度地减少内存不足错误(最大的一个胜利是使用未缓冲的查询并在返回结果集时处理数据和发出输出,而不是绕过巨大的数组)。

+1

是的,我应该,但它有点烦人在开发 – Jeffrey04 2010-02-25 08:17:49

+0

有时候致命的错误是无法控制的。有时候APC会处于不良状态,并会抛出错误,直到您重新启动apache。然后,奇迹般地,没有一个代码更改,致命的错误消失。 – 2011-09-15 21:42:34

+0

这个答案基本上是这样说的:“只需编写完美的代码并确保它是完美的,任何代码依赖的代码都是完美的。”好吧,我会在那里做对。 – Ellesedil 2015-09-17 19:29:11

3
function fatal_error_handler() { 

    if (@is_array($e = @error_get_last())) { 
    if (isset($e['type']) && $e['type']==1) { 
     header("Status: 500 Internal Server Error"); 
     header("HTTP/1.0 500 Internal Server Error"); 
     } 
    } 

} 
register_shutdown_function('fatal_error_handler'); 
28

PHP 确实一个致命错误发送一个HTTP 500。
让我举在this PHP bug-report评论(一Xdebug的错误阻止这种行为):

它确实发生了。它要求:

1)的display_errors =关闭
2)无标头尚未由错误发生
3)状态200是在该时间的时间发送。

<? 
    ini_set('display_errors', 0); 
    foobar(); 
    // This will return a http 500 
?> 

你能赶上致命错误有shutdown functionerror_get_last

register_shutdown_function(function() { 
    $lastError = error_get_last(); 

    if (!empty($lastError) && $lastError['type'] == E_ERROR) { 
     header('Status: 500 Internal Server Error'); 
     header('HTTP/1.0 500 Internal Server Error'); 
    } 
}); 
+2

如果你启用了xdebug,我不会这么做,它会用它自己的错误处理程序覆盖它,这似乎也会返回一个HTTP 200. – thaddeusmt 2015-09-29 21:25:05

2

我开发了一种方法来捕获所有错误类型在PHP(几乎所有)!我不知道E_CORE_ERROR(我认为它不会出现这个错误)!但是,对于其他致命错误(E_ERROR,E_PARSE,E_COMPILE ...),只使用一个错误处理函数就可以正常工作!有我的解决方案:

把下面的代码放在你的主文件(索引。php):

<?php 

define('E_FATAL', E_ERROR | E_USER_ERROR | E_PARSE | E_CORE_ERROR | 
     E_COMPILE_ERROR | E_RECOVERABLE_ERROR); 

define('ENV', 'dev'); 

//Custom error handling vars 
define('DISPLAY_ERRORS', TRUE); 
define('ERROR_REPORTING', E_ALL | E_STRICT); 
define('LOG_ERRORS', TRUE); 

register_shutdown_function('shut'); 

set_error_handler('handler'); 

//Function to catch no user error handler function errors... 
function shut(){ 

    $error = error_get_last(); 

    if($error && ($error['type'] & E_FATAL)){ 
     handler($error['type'], $error['message'], $error['file'], $error['line']); 
    } 

} 

function handler($errno, $errstr, $errfile, $errline) { 

    switch ($errno){ 

     case E_ERROR: // 1 // 
      $typestr = 'E_ERROR'; break; 
     case E_WARNING: // 2 // 
      $typestr = 'E_WARNING'; break; 
     case E_PARSE: // 4 // 
      $typestr = 'E_PARSE'; break; 
     case E_NOTICE: // 8 // 
      $typestr = 'E_NOTICE'; break; 
     case E_CORE_ERROR: // 16 // 
      $typestr = 'E_CORE_ERROR'; break; 
     case E_CORE_WARNING: // 32 // 
      $typestr = 'E_CORE_WARNING'; break; 
     case E_COMPILE_ERROR: // 64 // 
      $typestr = 'E_COMPILE_ERROR'; break; 
     case E_CORE_WARNING: // 128 // 
      $typestr = 'E_COMPILE_WARNING'; break; 
     case E_USER_ERROR: // 256 // 
      $typestr = 'E_USER_ERROR'; break; 
     case E_USER_WARNING: // 512 // 
      $typestr = 'E_USER_WARNING'; break; 
     case E_USER_NOTICE: // 1024 // 
      $typestr = 'E_USER_NOTICE'; break; 
     case E_STRICT: // 2048 // 
      $typestr = 'E_STRICT'; break; 
     case E_RECOVERABLE_ERROR: // 4096 // 
      $typestr = 'E_RECOVERABLE_ERROR'; break; 
     case E_DEPRECATED: // 8192 // 
      $typestr = 'E_DEPRECATED'; break; 
     case E_USER_DEPRECATED: // 16384 // 
      $typestr = 'E_USER_DEPRECATED'; break; 

    } 

    $message = '<b>'.$typestr.': </b>'.$errstr.' in <b>'.$errfile.'</b> on line <b>'.$errline.'</b><br/>'; 

    if(($errno & E_FATAL) && ENV === 'production'){ 

     header('Location: 500.html'); 
     header('Status: 500 Internal Server Error'); 

    } 

    if(!($errno & ERROR_REPORTING)) 
     return; 

    if(DISPLAY_ERRORS) 
     printf('%s', $message); 

    //Logging error on php file error log... 
    if(LOG_ERRORS) 
     error_log(strip_tags($message), 0); 

} 

ob_start(); 

@include 'content.php'; 

ob_end_flush(); 

?> 

我希望这可以帮助很多人!

+0

这是我第一次看到“Status:”HTTP头。 – wadim 2014-03-28 13:54:27