PHP: Wie sende ich einen HTTP-Antwortcode?


Antworten:


461

Ich habe gerade diese Frage gefunden und dachte, sie braucht eine umfassendere Antwort:

Ab PHP 5.4 gibt es drei Methoden, um dies zu erreichen:

Den Antwortcode selbst zusammenstellen (PHP> = 4.0)

Die header()Funktion hat einen speziellen Anwendungsfall, der eine HTTP-Antwortzeile erkennt und Sie durch eine benutzerdefinierte ersetzen kann

header("HTTP/1.1 200 OK");

Dies erfordert jedoch eine spezielle Behandlung für (schnelles) CGI-PHP:

$sapi_type = php_sapi_name();
if (substr($sapi_type, 0, 3) == 'cgi')
    header("Status: 404 Not Found");
else
    header("HTTP/1.1 404 Not Found");

Hinweis: Laut HTTP-RFC kann die Grundphrase eine beliebige benutzerdefinierte Zeichenfolge sein (die dem Standard entspricht). Aus Gründen der Clientkompatibilität empfehle ich jedoch nicht , dort eine zufällige Zeichenfolge einzufügen.

Hinweis: php_sapi_name() erfordert PHP 4.0.1

3. Argument zur Header-Funktion (PHP> = 4.3)

Es gibt offensichtlich einige Probleme bei der Verwendung dieser ersten Variante. Das größte davon ist meiner Meinung nach, dass es teilweise von PHP oder dem Webserver analysiert und schlecht dokumentiert wird.

Seit 4.3 verfügt die headerFunktion über ein drittes Argument, mit dem Sie den Antwortcode etwas bequemer festlegen können. Für die Verwendung dieses Codes muss das erste Argument jedoch eine nicht leere Zeichenfolge sein. Hier sind zwei Möglichkeiten:

header(':', true, 404);
header('X-PHP-Response-Code: 404', true, 404);

Ich empfehle die zweite ein . Der erste funktioniert in allen von mir getesteten Browsern, aber einige kleinere Browser oder Webcrawler haben möglicherweise ein Problem mit einer Kopfzeile, die nur einen Doppelpunkt enthält. Der Name des Headerfeldes im 2 .. Variante ist natürlich in keiner Weise standardisiert und könnte modifiziert werden, ich habe nur einen hoffentlich beschreibenden Namen gewählt.

http_response_code Funktion (PHP> = 5.4)

Die http_response_code()Funktion wurde in PHP 5.4 eingeführt und hat die Sache viel einfacher gemacht.

http_response_code(404);

Das ist alles.

Kompatibilität

Hier ist eine Funktion, die ich mir ausgedacht habe, als ich Kompatibilität unter 5.4 benötigte, aber die Funktionalität der "neuen" http_response_codeFunktion wollte. Ich glaube, PHP 4.3 ist mehr als genug Abwärtskompatibilität, aber man weiß nie ...

// For 4.3.0 <= PHP <= 5.4.0
if (!function_exists('http_response_code'))
{
    function http_response_code($newcode = NULL)
    {
        static $code = 200;
        if($newcode !== NULL)
        {
            header('X-PHP-Response-Code: '.$newcode, true, $newcode);
            if(!headers_sent())
                $code = $newcode;
        }       
        return $code;
    }
}

10
Ich kann bestätigen, dass header('X-PHP-Response-Code: 404', true, 404);dies unter PHP-FPM (FastCGI) ordnungsgemäß funktioniert
Josh

@dualed (1) würde nicht headers_sent()immer gleich nach dem Anruf wahr sein header()? (2) jemals etwas wie http_response_text () in der 5.4-Welt gefunden? Zumindest der alte Header () kann den Text nach dem Statuscode beeinflussen.
Bob Stein

@ BobStein-VisiBone (1) headers_sent() ist wahr, wenn Sie keine weiteren Header hinzufügen können, weil der Inhalt bereits gesendet wurde, und nicht, wenn Sie einen Header hinzugefügt haben. (2) Entschuldigung, nein. Andere Sprachen haben jedoch eine bessere Unterstützung
dualed

1
@Perry Der Grund, warum ich dies nicht vorschlage, ist der gleiche, warum ich nicht nur den Doppelpunkt vorschlage. PHP kann dies in allen Versionen unterschiedlich behandeln, da nicht definiert ist, was mit einem solchen "Header" passiert, es möglicherweise vollständig fehlschlägt - weder Header noch Status festgelegt oder ein ungültiger Header hinzugefügt wird (der http 1.1-Protokollstandard erfordert einen Doppelpunkt) )
Dualed

8
Ich habe Stunden damit verbracht zu erkennen, dass http_response_code(und vielleicht allgemeiner das Ändern des Headers) nach Ihnen echoetwas nicht mehr funktioniert . Ich hoffe es hilft.
Neptilo

40

Leider habe ich festgestellt, dass die von @dualed vorgestellten Lösungen verschiedene Mängel aufweisen.

  1. Die Verwendung substr($sapi_type, 0, 3) == 'cgi'ist nicht ausreichend, um schnelles CGI zu erkennen. Bei Verwendung von PHP-FPM FastCGI Process Manager wird php_sapi_name()fpm nicht cgi zurückgegeben

  2. Fasctcgi und php-fpm decken einen weiteren von @Josh erwähnten Fehler auf - die Verwendung header('X-PHP-Response-Code: 404', true, 404);funktioniert unter PHP-FPM (FastCGI) ordnungsgemäß.

  3. header("HTTP/1.1 404 Not Found");kann fehlschlagen, wenn das Protokoll nicht HTTP / 1.1 ist (dh 'HTTP / 1.0'). Das aktuelle Protokoll muss mit $_SERVER['SERVER_PROTOCOL'](verfügbar seit PHP 4.1.0) erkannt werden

  4. Es gibt mindestens zwei Fälle, in denen ein Anruf http_response_code()zu unerwartetem Verhalten führt:

    • Wenn PHP auf einen HTTP-Antwortcode stößt, den es nicht versteht, ersetzt PHP den Code durch einen Code, den es aus derselben Gruppe kennt. Beispiel: "521 Webserver ist ausgefallen" wird durch "500 Internal Server Error" ersetzt. Viele andere ungewöhnliche Antwortcodes aus anderen Gruppen 2xx, 3xx, 4xx werden auf diese Weise behandelt.
    • Auf einem Server mit der Funktion php-fpm und nginx http_response_code () kann der Code wie erwartet geändert werden, nicht jedoch die Nachricht. Dies kann beispielsweise zu einem seltsamen "404 OK" -Header führen. Dieses Problem wird auch auf der PHP-Website durch einen Benutzerkommentar http://www.php.net/manual/en/function.http-response-code.php#112423 erwähnt

Als Referenz finden Sie hier die vollständige Liste der HTTP-Antwortstatuscodes (diese Liste enthält Codes aus IETF-Internetstandards sowie andere IETF-RFCs. Viele von ihnen werden derzeit NICHT von der PHP-Funktion http_response_code unterstützt): http: //en.wikipedia .org / wiki / List_of_HTTP_status_codes

Sie können diesen Fehler einfach testen, indem Sie Folgendes aufrufen:

http_response_code(521);

Der Server sendet den HTTP-Antwortcode "500 Internal Server Error", der zu unerwarteten Fehlern führt, wenn beispielsweise eine benutzerdefinierte Clientanwendung Ihren Server aufruft und einige zusätzliche HTTP-Codes erwartet.


Meine Lösung (für alle PHP-Versionen seit 4.1.0):

$httpStatusCode = 521;
$httpStatusMsg  = 'Web server is down';
$phpSapiName    = substr(php_sapi_name(), 0, 3);
if ($phpSapiName == 'cgi' || $phpSapiName == 'fpm') {
    header('Status: '.$httpStatusCode.' '.$httpStatusMsg);
} else {
    $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0';
    header($protocol.' '.$httpStatusCode.' '.$httpStatusMsg);
}

Fazit

Die Implementierung von http_response_code () unterstützt nicht alle HTTP-Antwortcodes und überschreibt möglicherweise den angegebenen HTTP-Antwortcode mit einem anderen aus derselben Gruppe.

Die neue Funktion http_response_code () löst nicht alle damit verbundenen Probleme, verschlimmert jedoch die Einführung neuer Fehler.

Die von @dualed angebotene "Kompatibilitäts" -Lösung funktioniert zumindest unter PHP-FPM nicht wie erwartet.

Die anderen von @dualed angebotenen Lösungen weisen ebenfalls verschiedene Fehler auf. Die schnelle CGI-Erkennung unterstützt kein PHP-FPM. Das aktuelle Protokoll muss erkannt werden.

Alle Tests und Kommentare sind willkommen.


21

Seit PHP 5.4 können Sie http_response_code()den Header-Statuscode abrufen und festlegen.

hier ein Beispiel:

<?php

// Get the current response code and set a new one
var_dump(http_response_code(404));

// Get the new response code
var_dump(http_response_code());
?>

Hier ist das Dokument dieser Funktion in php.net:

http_response_code


Nach meiner Erfahrung ist dies die beste Antwort.
Scruffy

Warum var_dump () verwenden?
Tomas Gonzalez

Aber warum var_dump () statt Echo? Kann das Ergebnis nicht für ein einfaches Echo geeignet sein? Oder sogar print_r (). var_dump () scheint für den Produktionscode nicht ausreichend zu sein ...
Tomas Gonzalez

@TomasGonzalez es ist keine große Sache, ich wollte dir nur zeigen, was drin ist, indem du alles mit var_dump () druckst und du hast Recht, dass sie nicht wichtig sind
Seyed Ali Roshan

OK, ich verstehe. Was meine Aufmerksamkeit auf sich gezogen hat, ist, dass in den offiziellen Dokumenten das Beispiel auch var_dump () verwendet. Ich war also neugierig auf den Grund dafür. Es hätte etwas geben können, das mir gefehlt hat. php.net/manual/en/function.http-response-code.php
Tomas Gonzalez

10

Fügen Sie diese Zeile vor jeder Ausgabe des Körpers hinzu, falls Sie keine Ausgabepufferung verwenden.

header("HTTP/1.1 200 OK");

Ersetzen Sie den Nachrichtenteil ('OK') durch die entsprechende Nachricht und den Statuscode durch Ihren entsprechenden Code (404, 501 usw.).


2
Kann die Nachricht, die wir setzen (um das OK zu ersetzen), alles sein?
FMaz008

Das hat bei mir funktioniert. Ich habe an einem Kontaktformular auf einer Website mit PHP 5.3 gearbeitet. Und diese Lösung hat bei mir funktioniert. Es gibt einen Antworttext und diesen HTTP-Code für eine fehlgeschlagene AJAX-Anforderung. Das ist alles was ich wollte.
Surjith SM

7

Wenn Sie hier sind, weil Wordpress beim Laden der Umgebung 404 gibt, sollte dies das Problem beheben:

define('WP_USE_THEMES', false);
require('../wp-blog-header.php');
status_header( 200 );
//$wp_query->is_404=false; // if necessary

Das Problem ist darauf zurückzuführen, dass ein Status: 404 Not Found-Header gesendet wird. Das muss man außer Kraft setzen. Dies wird auch funktionieren:

define('WP_USE_THEMES', false);
require('../wp-blog-header.php');
header("HTTP/1.1 200 OK");
header("Status: 200 All rosy");

Header ("HTTP / 1.1 200 OK"); http_response_code (201); Header ("Status: 200 All rosy"); // Arbeit
Alpc

6

Mit der Header- Funktion. Im Abschnitt über den ersten Parameter finden Sie ein Beispiel.



2

Wenn Ihre PHP-Version diese Funktion nicht enthält:

<?php

function http_response_code($code = NULL) {
        if ($code !== NULL) {
            switch ($code) {
                case 100: $text = 'Continue';
                    break;
                case 101: $text = 'Switching Protocols';
                    break;
                case 200: $text = 'OK';
                    break;
                case 201: $text = 'Created';
                    break;
                case 202: $text = 'Accepted';
                    break;
                case 203: $text = 'Non-Authoritative Information';
                    break;
                case 204: $text = 'No Content';
                    break;
                case 205: $text = 'Reset Content';
                    break;
                case 206: $text = 'Partial Content';
                    break;
                case 300: $text = 'Multiple Choices';
                    break;
                case 301: $text = 'Moved Permanently';
                    break;
                case 302: $text = 'Moved Temporarily';
                    break;
                case 303: $text = 'See Other';
                    break;
                case 304: $text = 'Not Modified';
                    break;
                case 305: $text = 'Use Proxy';
                    break;
                case 400: $text = 'Bad Request';
                    break;
                case 401: $text = 'Unauthorized';
                    break;
                case 402: $text = 'Payment Required';
                    break;
                case 403: $text = 'Forbidden';
                    break;
                case 404: $text = 'Not Found';
                    break;
                case 405: $text = 'Method Not Allowed';
                    break;
                case 406: $text = 'Not Acceptable';
                    break;
                case 407: $text = 'Proxy Authentication Required';
                    break;
                case 408: $text = 'Request Time-out';
                    break;
                case 409: $text = 'Conflict';
                    break;
                case 410: $text = 'Gone';
                    break;
                case 411: $text = 'Length Required';
                    break;
                case 412: $text = 'Precondition Failed';
                    break;
                case 413: $text = 'Request Entity Too Large';
                    break;
                case 414: $text = 'Request-URI Too Large';
                    break;
                case 415: $text = 'Unsupported Media Type';
                    break;
                case 500: $text = 'Internal Server Error';
                    break;
                case 501: $text = 'Not Implemented';
                    break;
                case 502: $text = 'Bad Gateway';
                    break;
                case 503: $text = 'Service Unavailable';
                    break;
                case 504: $text = 'Gateway Time-out';
                    break;
                case 505: $text = 'HTTP Version not supported';
                    break;
                default:
                    exit('Unknown http status code "' . htmlentities($code) . '"');
                    break;
            }
            $protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
            header($protocol . ' ' . $code . ' ' . $text);
            $GLOBALS['http_response_code'] = $code;
        } else {
            $code = (isset($GLOBALS['http_response_code']) ? $GLOBALS['http_response_code'] : 200);
        }
        return $code;
    }

1

Wir können unterschiedliche Rückgabewerte von http_response_code über die zwei verschiedenen Umgebungen erhalten:

  1. Webserver-Umgebung
  2. CLI-Umgebung

Geben Sie in der Webserverumgebung den vorherigen Antwortcode zurück, wenn Sie einen Antwortcode angegeben haben oder wenn Sie keinen Antwortcode angeben, wird der aktuelle Wert gedruckt. Der Standardwert ist 200 (OK).

In der CLI-Umgebung wird true zurückgegeben, wenn Sie einen Antwortcode angegeben haben, und false, wenn Sie keinen Antwortcode angegeben haben.

Beispiel für eine Webserverumgebung mit dem Rückgabewert von Response_code:

var_dump(http_respone_code(500)); // int(200)
var_dump(http_response_code()); // int(500)

Beispiel für die CLI-Umgebung des Rückgabewerts von Response_code:

var_dump(http_response_code()); // bool(false)
var_dump(http_response_code(501)); // bool(true)
var_dump(http_response_code()); // int(501)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.