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 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');
Невозможно обрабатывать 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)
.
Трудная вещь при работе с фатальными ошибками (ошибки компиляции, например отсутствующая точка с запятой) заключается в том, что сценарий не будет выполнен, поэтому он не поможет установить код состояния в этом скрипте. Однако, когда вы включаете или требуете сценарий, исполняемый скрипт будет выполнен независимо от ошибок во включенном скрипте. При этом я прихожу к этому решению:
рок-твердое тело-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");
скрипт-я-хочу-к-охранником-для-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 отключена по умолчанию.