2010-02-25 20 views
14

Tengo un sitio de servicio web que está habilitado para descansar, por lo que otros sitios web/script ajax pueden realizar una llamada al sitio para obtener/establecer datos. Sin embargo, cada vez que el sitio de servicio web de alguna manera devuelve un error fatal PHP, el estado HTTP que se devuelve es 200 en lugar de 500. ¿Hay alguna forma de solucionarlo para que cada vez que se produzca un error fatal, devuelva 500 en lugar de 200? O, si no es posible, ¿cómo puedo cambiar mi cliente para reconocer el error fatal devuelto por el servicio web?Catch PHP Fatal Error

+0

Relacionados con http://stackoverflow.com/questions/3052715/php-how-to-return-an-http-500-code-on-any-error-no-matter-what – cweiske

Respuesta

13

Una forma posible sería establecer la respuesta por defecto a 500, si todo se ejecuta establecido con éxito la respuesta 200:

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

Agregue un búfer de página grande para evitar el infame error de salida que ya se inició y que debería hacerlo. – TheJacobTaylor

+1

Eso, o asegúrese de poner ' 'al principio de su secuencia de comandos en lugar de antes de la parte difícil. –

+3

También hay una solicitud de función de PHP abierta: http://bugs.php.net/bug.php?id=50921 – cweiske

3

Cree un controlador de error personalizado (set_error_handler) y llame al header("HTTP/1.0 500 Service not available");.

Editar:

por el primer comentario a mi respuesta, no se puede interceptar verdaderos errores fatales. Sin embargo, PHP establecerá de manera predeterminada un código de error 500 en los errores fatales si el almacenamiento en búfer de salida está deshabilitado y los errores no se muestran en la pantalla.

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

El código anterior arrojará un código de error 500 si no se ha enviado nada a la pantalla.

Así que si quieres este tipo de error para ajustar el código apropiado, hacer su propia búfer:

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

Gestores de errores personalizados pueden ' t atrapar errores fatales (por ejemplo, llamada al método en un objeto no, límite de tiempo/límite de memoria agotado) o errores de análisis. De los documentos: 'Los siguientes tipos de error no se pueden manejar con una función definida por el usuario: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING' http://php.net/set_error_handler –

+0

Sí, eso vale la pena mencionar. No estaba asumiendo que se refería a fatal literalmente, ya que algunas personas lo usan para referirse a cualquier tipo de error del que no se pueda recuperar. – Matthew

+0

: D realmente quiero decir error fatal XD – Jeffrey04

-5

me gustaría pensar que te gustaría atrapar y corregir todos los errores fatales antes de desplegar la aplicación, ya que muchos de ellos son errores de código, falta incluye, objetos que no existen, que son todo el desarrollo errores Incluso los errores de falta de memoria se pueden minimizar con técnicas de codificación frugal (una de las mayores ganancias es utilizar consultas sin búfer y procesar los datos y emitirlos a medida que se devuelve el conjunto de resultados, en lugar de arrojar enormes matrices).

+1

Sí, debería, pero es un poco molesto durante el desarrollo – Jeffrey04

+0

A veces los errores fatales están fuera de su control. APC se pone en mal estado a veces y arroja errores hasta que reinicie apache. Entonces, mágicamente, sin un solo cambio de código, los errores fatales desaparecen. –

+0

Esta respuesta básicamente dice: "Simplemente escribe el código perfecto y asegúrate de que sea perfecto, y cualquier cosa de la que dependa tu código también es perfecto". Ok, lo haré con eso. – Ellesedil

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 hace enviar un HTTP 500 en un error fatal.
Cito un comentario en this PHP bug-report (un error Xdebug evita este comportamiento):

a veces ocurre. Se requiere que:

1) display_errors = off
2) No se han enviado cabeceras todavía en el momento en que ocurre el error
3) de estado es 200 en ese momento.

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

Puede detectar errores fatales con un shutdown function y error_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

No quisiera que si tiene xdebug habilitado, anule esto con su propio controlador de errores, que también parece devolver un HTTP 200. – thaddeusmt

2

he desarrollado una manera de coger todos los tipos de errores en PHP (casi todos)! No estoy seguro acerca de E_CORE_ERROR (¡creo que no funcionará para ese error)! Pero, para otros errores fatales (E_ERROR, E_PARSE, E_COMPILE ...) funciona bien usando solo una función de controlador de errores. Ahí está mi solución:

Ponga este código en su archivo principal (índice.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(); 

?> 

Espero que esto ayude a muchas personas!

+0

Es la primera vez que veo un encabezado HTTP de "Estado:". – wadim

Cuestiones relacionadas