timonweb / gist:3165322
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
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 = ‘‘ . $ typestr . ‘: ‘ . $ errstr . ‘ in ‘ . $ errfile . ‘ on line ‘ . $ errline . ‘ ‘ ; |
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(); |
?> |
Как я могу заставить php возвратить 500, столкнувшись с фатальным исключением?
PHP фатальные ошибки возвращаются в качестве кода состояния 200 для HTTP-клиента. Как я могу заставить его вернуть код состояния 500 (Внутренняя ошибка сервера)?
header("HTTP/1.1 500 Internal Server Error");
Это именно та проблема, с которой я вчера столкнулся, и нашел решение следующим образом:
1) прежде всего, вам нужно уловить PHP фатальные ошибки, которые являются ошибкой E_ERROR. при возникновении этой ошибки скрипт будет хранить ошибку и прекратить выполнение. вы можете получить сохраненную ошибку, вызвав функцию error_get_last ().
2) до завершения сценария всегда будет вызываться функция обратного вызова register_shutdown_function (). поэтому вам необходимо зарегистрировать обработчик ошибок с помощью этой функции, чтобы сделать то, что вы хотите, в этом случае вернуть заголовок 500 и настроенную внутреннюю страницу ошибок (необязательно).
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');
Примечание. Если вы хотите поймать собственный тип ошибки, который начинается с E_USER *, вы можете использовать функцию set_error_handler () для регистрации обработчика ошибок и запускать ошибку с помощью функции trigger_error, однако этот обработчик ошибок не может обрабатывать тип ошибки E_ERROR. см. объяснение на php.net о обработчике ошибок
Я использовал «set_exception_handler» для обработки исключений uncaught.
function handleException($ex) < error_log("Uncaught exception . 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');
Невозможно обрабатывать PHP E_ERROR каким-либо образом в соответствии с документацией PHP: 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, когда код приложения сбой и ожоги.
Вы можете использовать обработку ошибок php
Вам придется поймать заброшенную ошибку с помощью try / catch, а затем использовать этот блок catch для отправки заголовка () с ошибкой 500.
try < . badcode. throw new Exception('error'); >catch (Exception $e) < header("Status: 500 Server Error"); var_dump($e->getMessage()); >
Если фатальное исключение не окружено блоками try <> catch, вы должны зарегистрировать глобальный обработчик и использовать register_shutdown_function() чтобы проверить наличие ошибки на конце скрипта.
Никогда не забудьте установить 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 вы можете заменить вышеописанную функцию header гораздо лучше http_response_code(200) или http_response_code(500) .
Трудная вещь при работе с фатальными ошибками (ошибки компиляции, например отсутствующая точка с запятой) заключается в том, что сценарий не будет выполнен, поэтому он не поможет установить код состояния в этом скрипте. Однако, когда вы включаете или требуете сценарий, исполняемый скрипт будет выполнен независимо от ошибок во включенном скрипте. При этом я прихожу к этому решению:
// 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");
// 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
Направьте свой звонок на rock-solid-script.php, и вы готовы к работе.
Мне бы лучше было установить код состояния по умолчанию на 500 в .htaccess. Это кажется мне более элегантным, но я не могу найти способ его снять. Я попробовал флаг RewriteRule R, но это предотвращает выполнение php вообще, так что это бесполезно.
Стандартная конфигурация PHP возвращает 500 при возникновении ошибки! Просто убедитесь, что ваш display_errors = выключен. Вы можете имитировать его с помощью:
ini_set('display_errors', 0); noFunction();
По умолчанию директива display_errors отключена по умолчанию.
Send a 500 Internal Server Error header with PHP.
This is a short guide on how to send a 500 Internal Server Error header to the client using PHP. This is useful because it allows us to tell the client that the server has encountered an unexpected condition and that it cannot fulfill the request.
Below, I have created a custom PHP function called internal_error.
//Function that sends a 500 Internal Server Error status code to //the client before killing the script. function internal_error()< header($_SERVER["SERVER_PROTOCOL"] . ' 500 Internal Server Error', true, 500); echo 'Something went wrong!
'; exit; >
When the PHP function above is called, the script’s execution is halted and “Something went wrong!” is printed out onto the page.
Furthermore, if you inspect the HTTP headers with your browser’s developer console, you will see that the function is returning a 500 Internal Server Error status code:
Google’s Developer Tools showing the 500 Internal Server Error status that was returned.
To send the 500 status code, we used PHP’s header function like so:
//Send a 500 status code using PHP's header function header($_SERVER["SERVER_PROTOCOL"] . ' 500 Internal Server Error', true, 500);
Note that we used the SERVER_PROTOCOL variable in this case because the client might be using HTTP 1.0 instead of HTTP 1.1. In other examples, you will find developers making the assumption that the client will always be using HTTP 1.1.
The problem with PHP is that it doesn’t always send a 500 Internal Server Error when an exception is thrown or a fatal error occurs.
This can cause a number of issues:
- It becomes more difficult to handle failed Ajax calls, as the server in question is still responding with a 200 OK status. For example: The JQuery Ajax error handling functions will not be called.
- Search engines such as Google may index your error pages. If this happens, your website may lose its rankings.
- Other HTTP clients might think that everything is A-OK when it is not.
Note that if you are using PHP version 5.4 or above, you can use the http_response_code function:
//Using http_response_code http_response_code(500);