So senden Sie 500 Internal Server Error-Fehler aus einem PHP-Skript

80

Ich muss unter bestimmten Bedingungen "500 Internal Server Error" von einem PHP-Skript senden. Das Skript soll von einer Drittanbieter-App aufgerufen werden. Das Skript enthält einige die("this happend")Anweisungen, für die ich 500 Internal Server Erroranstelle des üblichen den Antwortcode senden muss 200 OK. Das Skript eines Drittanbieters sendet die Anforderung unter bestimmten Bedingungen erneut, einschließlich des Nichtempfangs des 200 OKAntwortcodes.

Zweiter Teil der Frage: Ich muss mein Skript folgendermaßen einrichten:

<?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" );
?>

Ich muss den 200Header erst senden, nachdem die letzte Zeile ausgeführt wurde.

Bearbeiten

Eine Nebenfrage: Kann ich seltsame 500 Header wie diese senden:

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

Werden solche Fehler vom Webserver protokolliert?

Salman A.
quelle
ist nicht machbar, wenn Sie Header gesendet und Header später entfernen
Ajreal
1
Nebenfrage: Das ist völlig legitim. Grund Sätze sind nicht für den Maschinenverbrauch gedacht und können alles sein. Es kommt nur auf den dreistelligen Statuscode an. (RFC2616 6.1.1: "Die hier aufgeführten Grundsätze sind nur Empfehlungen - sie können durch lokale Entsprechungen ersetzt werden, ohne das Protokoll zu beeinflussen.")
Piskvor verließ das Gebäude

Antworten:

167
header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500);
Kern Xii
quelle
Zu Ihrer Information, diese Lösung sendet das X-Pad: Vermeiden Sie Browser-Bug-Header in einigen Versionen von Apache. stackoverflow.com/questions/8711584/… . http_response_code()lässt diesen Header weg.
Anthony Rutledge
3
Das funktioniert sogar, wenn der Header nicht am Anfang steht (z. B. ein Arbeitsnachweis), gute Arbeit.
Ich bin ich
43

PHP 5.4 hat eine Funktion namens http_response_code . Wenn Sie also PHP 5.4 verwenden, können Sie einfach Folgendes tun:

http_response_code(500);

Ich habe eine Polyfüllung für diese Funktion (Gist) geschrieben, wenn Sie eine Version von PHP unter 5.4 ausführen.


Zur Beantwortung Ihrer Folgefrage lautet der HTTP 1.1-RFC:

Die hier aufgeführten Grundsätze sind nur Empfehlungen - sie können durch lokale Entsprechungen ersetzt werden, ohne das Protokoll zu beeinflussen.

Das heißt, Sie können nach dem Code selbst beliebigen Text verwenden (ausgenommen Zeilenumbrüche oder Zeilenvorschübe), und es funktioniert. Im Allgemeinen gibt es jedoch normalerweise einen besseren Antwortcode. Anstatt beispielsweise eine 500 für keinen gefundenen Datensatz zu verwenden, könnten Sie eine 404 (nicht gefunden) senden , und für etwas wie "Bedingungen fehlgeschlagen" (ich vermute einen Validierungsfehler) könnten Sie eine 422 senden (nicht verarbeitbar) Entität).

inxilpro
quelle
Es ist wichtig zu beachten, dass diese Funktion auch nach dem Start der Ausgabe nicht mehr funktioniert!
Rob74
@ rob74 True - Sobald PHP mit dem Senden der Ausgabe begonnen hat, funktionieren alle Header-bezogenen Funktionen nicht mehr. Wenn Sie nicht sicher sind, ob Sie den Antwortcode ändern müssen, bevor Sie mit dem Senden der Ausgabe beginnen, ist die Ausgabepufferung eine gute Lösung.
Inxilpro
33

Sie können die folgende Funktion verwenden, um eine Statusänderung zu senden:

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);
    }
}

Sie können es als solches verwenden:

<?php
header_status(500);

if (that_happened) {
    die("that happened")
}

if (something_else_happened) {
    die("something else happened")
}

update_database();

header_status(200);
Andrew Moore
quelle
21
Das Speichern von ein paar Bytes Speicher ist selten ein guter Grund, Webanwendungscode auf die eine oder andere Weise zu schreiben.
Dan Grossman
1
Vermissen Sie nicht ein ;After die()?
Henrywright
1
Ihre Liste fehlt 418 => "Ich bin eine Teekanne" siehe: en.wikipedia.org/wiki/Hyper_Text_Coffee_Pot_Control_Protocol
Louis Loudog Trottier
15

Sie können einfach sagen:

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

innerhalb Ihrer Bedingungen wie:

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

Bei der Datenbankabfrage können Sie dies wie folgt tun:

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

Sie sollten sich daran erinnern, dass Sie diesen Code vor jedem HTML-Tag (oder jeder Ausgabe) einfügen müssen.

Ruel
quelle
11
Stellen Sie sicher, dass Sie / die / return / etwas verlassen, nachdem Sie header () aufgerufen haben. PHP führt weiterhin Code aus - was wahrscheinlich nicht wünschenswert ist.
David Goodwin
8

Sie können es folgendermaßen vereinfachen:

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

Es wird folgender Header zurückgegeben:

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

Hinzugefügt: Wenn Sie genau wissen müssen, was schief gelaufen ist, gehen Sie wie folgt vor:

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');
}
David Kuridža
quelle
5
Was 'x'soll nun sein?
Core Xii
1
+1 Beachten Sie, dass der erste Parameter in headereine nicht leere Zeichenfolge sein muss. Dass es 'x'nicht wirklich wichtig ist.
Theazureshadow
1
@Core Xii, der erste Parameter darf nicht null sein, wie @theazureshadow hervorhob. Kurz gesagt, durch Aufrufen des Headers ('etwas', true, 500) wird der korrekte Header "HTTP / 1.0 500 Internal Server Error" zurückgegeben. Sie können mich als faul bezeichnen, aber es ist einfacher, nur den Fehlercode zu übergeben, als die eigentliche Header-Zeichenfolge zu verarbeiten :) Weitere Informationen finden Sie unter php.net/manual/en/function.header.php .
David Kuridža
Das Handbuch ist darüber nicht sehr klar. Sie sagen also, wenn Sie den Statuscode erzwingen, überschreibt PHP das String-Argument automatisch auf den richtigen Wert? Warum sollte das Handbuch dann sagen, dass es nur wirksam wird, wenn die Zeichenfolge nicht leer ist?
Core Xii
1
Beachten Sie, dass in einigen PHP-Konfigurationen (die von meinem Hosting-Anbieter zum Beispiel verwendet werden, aber nicht von meinem lokalen Setup) dieser Trick nicht funktioniert! Apache erkennt "x" nicht als korrekte Header-Zeichenfolge und schlägt mit einem "Fehlgebildeten Header" -Fehler fehl.
mjsarfatti
2

Ihr Code sollte folgendermaßen aussehen:

<?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');
?>

Ich gehe davon aus, dass Sie die Ausführung beenden, wenn etwas schief geht.

Sébastien VINCENT
quelle