Как отправить 500 ошибок внутреннего сервера из сценария PHP

Мне нужно отправить «500 Internal Server Error» из скрипта PHP при определенных условиях. Сценарий должен быть вызван сторонним приложением. Сценарий содержит пару выражений die("this happend") для которых мне нужно отправить код ответа 500 Internal Server Error вместо обычных 200 OK . Третий сторонний скрипт будет повторно отправлять запрос при определенных условиях, которые не включают код ответа 200 OK .

Вторая часть вопроса: мне нужно настроить мой скрипт следующим образом:

 <?php custom_header( "500 Internal Server Error" ); if ( that_happened ) { die( "that happened" ) } if ( something_else_happened ) { die( "something else happened" ) } update_database( ); // the script can also fail on the above line // eg a mysql error occurred remove_header( "500" ); ?> 

Мне нужно отправить 200 заголовков только после того, как была выполнена последняя строка.

редактировать

Боковой вопрос: могу ли я отправить странные 500 заголовков, таких как:

 HTTP/1.1 500 No Record Found HTTP/1.1 500 Script Generated Error (E_RECORD_NOT_FOUND) HTTP/1.1 500 Conditions Failed on Line 23 

Будут ли такие ошибки регистрироваться на веб-сервере?

 header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500); 

Вы можете использовать следующую функцию для отправки изменения статуса:

 function header_status($statusCode) { static $status_codes = null; if ($status_codes === null) { $status_codes = array ( 100 => 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-Status', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 307 => 'Temporary Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Timeout', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Long', 415 => 'Unsupported Media Type', 416 => 'Requested Range Not Satisfiable', 417 => 'Expectation Failed', 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', 426 => 'Upgrade Required', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Timeout', 505 => 'HTTP Version Not Supported', 506 => 'Variant Also Negotiates', 507 => 'Insufficient Storage', 509 => 'Bandwidth Limit Exceeded', 510 => 'Not Extended' ); } if ($status_codes[$statusCode] !== null) { $status_string = $statusCode . ' ' . $status_codes[$statusCode]; header($_SERVER['SERVER_PROTOCOL'] . ' ' . $status_string, true, $statusCode); } } 

Вы можете использовать его как таковое:

 <?php header_status(500); if (that_happened) { die("that happened") } if (something_else_happened) { die("something else happened") } update_database(); header_status(200); 

PHP 5.4 имеет функцию http_response_code , поэтому, если вы используете PHP 5.4, вы можете просто сделать:

 http_response_code(500); 

Я написал polyfill для этой функции (Gist), если вы используете версию PHP под 5.4.


Чтобы ответить на ваш последующий вопрос, HTTP 1.1 RFC говорит:

Приведенные здесь фразы причины – это только рекомендации – они МОГУТ быть заменены локальными эквивалентами, не затрагивая протокол.

Это означает, что вы можете использовать любой текст, который вы хотите (исключая возврат каретки или линейные каналы) после самого кода, и он будет работать. Как правило, обычно используется лучший код ответа. Например, вместо того, чтобы использовать 500 без записи, вы можете отправить 404 (не найдено), а для чего-то вроде «условия не удались» (я предполагаю ошибку проверки), вы могли бы отправить что-то вроде 422 (непроцессорный организация).

Вы можете просто поставить:

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

в ваших условиях:

 if (that happened) { header("HTTP/1.0 500 Internal Server Error"); } 

Что касается запроса к базе данных, вы можете просто сделать это вот так:

 $result = mysql_query("..query string..") or header("HTTP/1.0 500 Internal Server Error"); 

Вы должны помнить, что вы должны поместить этот код перед любым тегом html (или выходом).

Вы можете упростить его так:

 if ( that_happened || something_else_happened ) { header('X-Error-Message: Incorrect username or password', true, 500); die; } 

Он вернет следующий заголовок:

 HTTP/1.1 500 Internal Server Error ... X-Error-Message: Incorrect username or password ... 

Добавлено: Если вам нужно точно знать, что пошло не так, сделайте что-то вроде этого:

 if ( that_happened ) { header('X-Error-Message: Incorrect username', true, 500); die('Incorrect username'); } if ( something_else_happened ) { header('X-Error-Message: Incorrect password', true, 500); die('Incorrect password'); } 

Ваш код должен выглядеть так:

 <?php if ( that_happened ) { header("HTTP/1.0 500 Internal Server Error"); die(); } if ( something_else_happened ) { header("HTTP/1.0 500 Internal Server Error"); die(); } // Your function should return FALSE if something goes wrong if ( !update_database() ) { header("HTTP/1.0 500 Internal Server Error"); die(); } // the script can also fail on the above line // eg a mysql error occurred header('HTTP/1.1 200 OK'); ?> 

Я предполагаю, что вы прекратите выполнение, если что-то пойдет не так.