Как отправить 500 внутренняя ошибка сервера из сценария PHP - PullRequest
71 голосов
/ 12 ноября 2010

Мне нужно отправить «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
    // e.g. 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

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

Ответы [ 6 ]

161 голосов
/ 12 ноября 2010
header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500);
38 голосов
/ 26 февраля 2014

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

http_response_code(500);

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


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

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

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

33 голосов
/ 12 ноября 2010

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

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);
15 голосов
/ 12 ноября 2010

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

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-тегом (или выводом).

8 голосов
/ 12 ноября 2010

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

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');
}
2 голосов
/ 12 ноября 2010

Ваш код должен выглядеть следующим образом:

<?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
// e.g. a mysql error occurred


header('HTTP/1.1 200 OK');
?>

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

...