PHP: comment envoyer du code de réponse HTTP?

j'ai un script PHP qui a besoin de faire des réponses avec des codes de réponse HTTP (status-codes), comme HTTP 200 OK, ou quelque code 4XX ou 5XX.

Comment puis-je faire cela en PHP?

189
demandé sur hakre 2010-07-15 22:23:56

7 réponses

je viens de trouver cette question et j'ai pensé qu'elle avait besoin d'une réponse plus complète:

Que de PHP 5.4 il y a trois méthodes pour cela:

Montage du code de réponse sur votre propre (PHP >= 4.0)

la fonction header() 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 , la reason phrase peut être n'importe quelle chaîne personnalisée (qui est conforme à la norme), mais pour des raisons de compatibilité avec les clients, je ne recommande pas d'y placer une chaîne aléatoire.

Note: php_sapi_name() exige PHP 4.0.1

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

Il y a évidemment quelques problèmes lors de l'utilisation de cette première variante. Le plus important, je pense, c'est qu'il est partiellement analysé par PHP ou le serveur web et mal documenté.

depuis 4.3, la fonction header a un 3ème argument qui vous permet de définir le code de réponse un peu confortablement, mais elle nécessite le premier argument une chaîne non vide. Voici deux options:

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

je recommande le 2e . Le premier fait travail sur tous les navigateurs que j'ai testé, mais certains navigateurs mineurs ou web crawlers peuvent avoir un problème avec une ligne d'en-tête qui ne contient que deux points. Le champ d'en-tête nom dans le 2ème. la variante n'est évidemment pas standardisée et pourrait être modifiée, J'ai juste choisi une, espérons-le nom descriptif.

fonction http_response_code (PHP >= 5.4)

la fonction http_response_code() a été introduite dans PHP 5.4, et il a rendu les choses beaucoup plus facile.

http_response_code(404);

C'est tout.

compatibilité

Voici une fonction que j'ai concoctée quand j'avais besoin de compatibilité en dessous de 5.4 mais voulait la fonctionnalité de la" nouvelle " http_response_code fonction. Je crois que PHP 4.3 est plus qu'assez rétro-compatibilité, 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;
    }
}
363
répondu dualed 2012-08-18 12:46:40

malheureusement, j'ai trouvé que les solutions présentées par @dualed ont plusieurs défauts.

  1. L'utilisation de substr($sapi_type, 0, 3) == 'cgi' n'est pas suffisante pour détecter les CGI rapides. Lors de L'utilisation de PHP-FPM FastCGI Process Manager, php_sapi_name() renvoie FPM pas cgi

  2. Fasctcgi et php-fpm exposent un autre bug mentionné par @Josh-l'utilisation de 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 HTTP/1.1 (c 'HTTP/1.0'). Le protocole actuel doit être détecté en utilisant $_SERVER['SERVER_PROTOCOL'] (disponible depuis PHP 4.1.0

  4. il y a au moins deux cas où l'appel http_response_code() entraîne un comportement inattendu:

    • lorsque PHP rencontre un code de réponse HTTP qu'il ne comprend pas, PHP remplacera le code par un code qu'il connaît du même groupe. Par exemple " 521 Web server is down "est remplacé par"500 Internal Server Error". De nombreux autres codes de réponse peu communs des autres groupes 2xx, 3xx, 4xx sont traités de cette façon.
    • sur un serveur avec la fonction php-fpm et nginx http_response_code() peut changer le code comme prévu mais pas le message. Il peut en résulter un en-tête étrange "404 OK" par exemple. Ce problème est également mentionné sur le site Web de PHP par un commentaire de l'utilisateur http://www.php.net/manual/en/function.http-response-code.php#112423

pour votre référence ici, il y a la liste complète des codes D'état de réponse HTTP (cette liste inclut les codes des normes internet de l'IETF ainsi que d'autres RFC de l'IETF. Beaucoup D'entre eux ne sont pas actuellement 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 bogue en appelant:

http_response_code(521);

le serveur enverra le code de réponse HTTP" 500 Internal Server Error " résultant en des erreurs imprévues si vous avez par exemple une application client personnalisée appelant votre serveur et s'attendant à des codes HTTP supplémentaires.


ma solution (pour toutes les versions 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 supporte pas tous les codes de réponse HTTP et peut écraser le code de réponse HTTP spécifié avec un autre du même groupe.

la nouvelle fonction http_response_code() ne résout pas tous les problèmes impliqués mais rend les choses plus difficiles en introduisant de nouveaux bogues.

la solution de" compatibilité " offerte par @dualed ne fonctionne pas comme prévu, à moins sous PHP-FPM.

les autres solutions proposées par @dualed ont aussi divers bugs. La détection rapide de CGI ne traite pas PHP-FPM. Protocole actuel doit être détecté.

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

29
répondu Grigore Madalin 2015-05-27 21:54:38

Ajouter cette ligne avant toute sortie du corps, dans le cas où vous n'utilisez pas de tampon de sortie.

header("HTTP/1.1 200 OK");

remplacer la partie du message ('OK') par le message approprié, et le code d'état par votre code selon le cas (404, 501, etc)

7
répondu sparkey0 2010-07-15 18:27:02

depuis PHP 5.4 vous pouvez utiliser http_response_code() pour obtenir et définir le code d'état d'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

7
répondu Seyed Ali Roshan 2017-01-06 15:54:17

avec la fonction header . Il y a un exemple dans la section sur le premier paramètre qu'il faut.

5
répondu Quentin 2010-07-15 18:26:35

si vous êtes ici en raison de Wordpress donnant 404 's lors du chargement de l'environnement, cela devrait corriger 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 en-tête Status: 404 Not Found. Vous devez remplacer. Cela fonctionnera aussi:

define('WP_USE_THEMES', false);
require('../wp-blog-header.php');
header("HTTP/1.1 200 OK");
header("Status: 200 All rosy");
5
répondu jaggedsoft 2013-08-13 08:21:31
header("HTTP/1.1 200 OK");
http_response_code(201);

http_response_code (200); ne fonctionne pas car test alert 404 https://developers.google.com/speed/pagespeed/insights /

1
répondu alpc 2016-06-21 15:59:20