Как я могу заставить php вернуть 500 после фатального исключения? - PullRequest
49 голосов
/ 12 октября 2009

Неустранимые ошибки PHP возвращаются в виде кода состояния 200 клиенту HTTP. Как заставить его вернуть код состояния 500 (Внутренняя ошибка сервера)?

Ответы [ 9 ]

49 голосов
/ 12 октября 2009
header("HTTP/1.1 500 Internal Server Error");
23 голосов
/ 13 января 2012

Это именно та проблема, которая у меня была вчера, и я нашел решение следующим образом:

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 о обработчике ошибок

6 голосов
/ 23 сентября 2010

Я использовал set_exception_handler для обработки необработанных исключений.

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');
3 голосов
/ 05 апреля 2016

Стандартная конфигурация PHP делает возвращает 500 при возникновении ошибки! Просто убедитесь, что ваш display_errors = off. Вы можете смоделировать это с помощью:

ini_set('display_errors', 0); 
noFunction();

На производстве директива display_errors по умолчанию отключена.

3 голосов
/ 24 января 2010

Невозможно обработать 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, когда код приложения падает и горит.

1 голос
/ 22 февраля 2013

Трудно при работе с фатальными ошибками (ошибками компиляции, например, отсутствующей точкой с запятой), что скрипт не будет выполнен, поэтому он не поможет установить код состояния в этом скрипте. Однако когда вы включаете или запрашиваете скрипт, вызывающий скрипт будет выполняться независимо от ошибок во включенном скрипте. С этим я прихожу к этому решению:

незыблемый-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. Это кажется более элегантным для меня, но я не могу найти способ осуществить это. Я попробовал R-флаг RewriteRule, но это вообще мешает выполнению php, так что это бесполезно.

0 голосов
/ 01 августа 2012

Никогда не забывайте устанавливать 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).

0 голосов
/ 12 октября 2009

Вам нужно было бы перехватить сгенерированную ошибку, используя try / catch , а затем использовать этот блок catch для отправки header () с ошибкой 500.

try {
    ...badcode...
    throw new Exception('error');

} catch (Exception $e) {

    header("Status: 500 Server Error");
    var_dump($e->getMessage());
}

Если фатальное исключение не окружено блоками перехвата try {}, вы должны зарегистрировать глобальный обработчик и использовать register_shutdown_function(), чтобы проверить наличие ошибки в конце скрипта.

0 голосов
/ 12 октября 2009

Вы можете использовать обработку ошибок php

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

...