Question

J'ai un script PHP qui doit faire des réponses avec des codes de réponse HTTP (codes d'état), comme HTTP 200 OK, ou du code 4XX ou 5XX.

Comment puis-je faire cela en PHP ?

Était-ce utile?

La solution

Je viens de trouver cette question et j'ai pensé qu'elle nécessitait une réponse plus complète :

Dès PHP5.4 il existe trois méthodes pour y parvenir :

Assembler vous-même le code de réponse (PHP >= 4.0)

Le header() la fonction a un cas d'utilisation spécial qui détecte une ligne de réponse HTTP et vous permet de la remplacer par une ligne personnalisée

header("HTTP/1.1 200 OK");

Cependant, cela nécessite un traitement spécial pour (Fast)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");

Note: Selon le HTTP RFC, le phrase de raison peut être n'importe quelle chaîne personnalisée (conforme à la norme), mais pour des raisons de compatibilité client, je ne pas recommande d'y mettre une chaîne aléatoire.

Note: php_sapi_name() a besoin PHP4.0.1

3ème argument de la fonction d'en-tête (PHP >= 4.3)

L’utilisation de cette première variante pose évidemment quelques problèmes.Le plus important, à mon avis, est qu'il est en partie analysé par PHP ou le serveur Web et mal documenté.

Depuis la version 4.3, le header La fonction a un troisième argument qui vous permet de définir le code de réponse de manière assez confortable, mais son utilisation nécessite que le premier argument soit une chaîne non vide.Voici deux options :

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

je recommande le 2ème.La première fait fonctionne sur tous les navigateurs que j'ai testés, mais certains navigateurs mineurs ou robots d'exploration Web peuvent avoir un problème avec une ligne d'en-tête qui ne contient que deux points.Le nom du champ d'en-tête dans le 2ème.La variante n'est bien sûr en aucun cas standardisée et pourrait être modifiée, j'ai juste choisi un nom, je l'espère, descriptif.

Fonction http_response_code (PHP >= 5.4)

Le http_response_code() fonction a été introduite dans PHP 5.4, et elle a rendu les choses beaucoup Plus facile.

http_response_code(404);

C'est tout.

Compatibilité

Voici une fonction que j'ai concoctée lorsque j'avais besoin d'une compatibilité inférieure à 5.4 mais que je voulais la fonctionnalité du "nouveau" http_response_code fonction.Je pense que PHP 4.3 est plus que suffisant pour une rétrocompatibilité, mais on ne sait jamais...

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

Autres conseils

Malheureusement, j'ai trouvé que les solutions présentées par @dualed présentaient divers défauts.

  1. En utilisant substr($sapi_type, 0, 3) == 'cgi' n'est pas suffisant pour détecter des CGI rapides.Lors de l'utilisation de PHP-FPM FastCGI Process Manager, php_sapi_name() renvoie fpm et non cgi

  2. Fasctcgi et php-fpm exposent un autre bug mentionné par @Josh - en utilisant header('X-PHP-Response-Code: 404', true, 404); fonctionne correctement sous PHP-FPM (FastCGI)

  3. header("HTTP/1.1 404 Not Found"); peut échouer lorsque le protocole n'est pas HTTP/1.1 (c'est-à-dire'HTTP/1.0').Le protocole actuel doit être détecté à l'aide $_SERVER['SERVER_PROTOCOL'] (disponible depuis PHP 4.1.0

  4. Il y a au moins 2 cas lors de l'appel http_response_code() entraîner un comportement inattendu :

    • Lorsque PHP rencontre un code de réponse HTTP qu'il ne comprend pas, PHP remplace le code par un code qu'il connaît et appartenant au même groupe.Par exemple, « 521 Le serveur Web est en panne » est remplacé par « 500 Erreur de serveur interne ».De nombreux autres codes de réponse inhabituels provenant d'autres groupes 2xx, 3xx, 4xx sont traités de cette façon.
    • Sur un serveur avec php-fpm et nginx, la fonction http_response_code() PEUT changer le code comme prévu mais pas le message.Cela peut donner lieu à un étrange en-tête "404 OK" par exemple.Ce problème est également mentionné sur le site PHP par un commentaire utilisateur http://www.php.net/manual/en/function.http-response-code.php#112423

Pour votre référence, vous trouverez ici la liste complète des codes d'état de réponse HTTP (cette liste comprend les codes des normes Internet de l'IETF ainsi que d'autres RFC de l'IETF.Beaucoup d'entre eux ne sont actuellement PAS pris en charge par la fonction PHP http_response_code) : http://en.wikipedia.org/wiki/List_of_HTTP_status_codes

Vous pouvez facilement tester ce bug en appelant :

http_response_code(521);

Le serveur enverra le code de réponse HTTP « 500 Internal Server Error », ce qui entraînera des erreurs inattendues si vous avez par exemple une application client personnalisée appelant votre serveur et attendant des codes HTTP supplémentaires.


Ma solution (pour toutes les versions de PHP depuis 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);
}

Conclusion

L'implémentation http_response_code() ne prend pas en charge tous les codes de réponse HTTP et peut écraser le code de réponse HTTP spécifié par un autre du même groupe.

La nouvelle fonction http_response_code() ne résout pas tous les problèmes impliqués mais aggrave les choses en introduisant de nouveaux bugs.

La solution "compatibilité" proposée par @dualed ne fonctionne pas comme prévu, du moins sous PHP-FPM.

Les autres solutions proposées par @dualed présentent également divers bugs.La détection CGI rapide ne gère pas PHP-FPM.Le protocole actuel doit être détecté.

Tous les tests et commentaires sont appréciés.

depuis PHP 5.4, vous pouvez utiliser http_response_code() pour obtenir et définir le code d’état de l’en-tête.

voici un exemple :

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

voici le document de cette fonction en php.net :

http_response_code

Ajoutez cette ligne avant toute sortie du corps, dans le cas où vous n'utilisez pas la mémoire tampon de sortie.

header("HTTP/1.1 200 OK");

Remplacez la partie de message ('OK') avec le message approprié et le code d'état avec votre code selon le cas (404, 501, etc.)

Si vous êtes ici à cause de WordPress donnant 404 lors du chargement de l'environnement, cela devrait résoudre le problème:

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

Le problème est dû à l'envoi d'un statut: 404 Indiquée non trouvée.Vous devez remplacer cela. Cela fonctionnera également:

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

avec le en-tête fonction.Il y a un exemple dans la section sur le premier paramètre qu'il faut.

Si votre version de PHP n'inclut pas cette fonction:

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

We can get different return value from http_response_code via the two different environment:

  1. Web Server Environment
  2. CLI environment

At the web server environment, return previous response code if you provided a response code or when you do not provide any response code then it will be print the current value. Default value is 200 (OK).

At CLI Environment, true will be return if you provided a response code and false if you do not provide any response_code.

Example of Web Server Environment of Response_code's return value:

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

Example of CLI Environment of Response_code's return value:

var_dump(http_response_code()); // bool(false)
var_dump(http_response_code(501)); // bool(true)
var_dump(http_response_code()); // int(501)
header("HTTP/1.1 200 OK");
http_response_code(201);
header("Status: 200 All rosy");

http_response_code(200); not work because test alert 404 https://developers.google.com/speed/pagespeed/insights/

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top