开发者

How can I get php to return 500 upon encountering a fatal exception?

PHP fatal errors come back as status code 200 to the HTTP clien开发者_StackOverflow社区t. How can I make it return a status code 500 (Internal server error)?


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


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


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.


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


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.


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.


You can use php error handling

http://www.w3schools.com/php/php_error.asp


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.


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).


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜