J'ai un script PHP qui doit répondre avec des codes de réponse HTTP (codes de statut), comme HTTP 200 OK, ou un code 4XX ou 5XX.
Comment puis-je faire cela en PHP ?
J'ai un script PHP qui doit répondre avec des codes de réponse HTTP (codes de statut), comme HTTP 200 OK, ou un code 4XX ou 5XX.
Comment puis-je faire cela en PHP ?
Je viens de trouver cette question et j'ai pensé qu'elle nécessitait une réponse plus complète :
A partir de PHP 5.4 Il existe trois méthodes pour y parvenir :
Le site 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 le PHP (Fast)CGI :
$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 RFC HTTP le phrase de motivation peut être n'importe quelle chaîne personnalisée (conforme à la norme), mais pour des raisons de compatibilité avec le client, j'ai décidé d'utiliser l'option ne pas recommande d'y mettre une chaîne aléatoire.
Note : php_sapi_name()
nécessite PHP 4.0.1
L'utilisation de cette première variante pose évidemment quelques problèmes. Le plus important est qu'elle est partiellement analysée par PHP ou le serveur web et qu'elle est mal documentée.
Depuis 4.3, le header
possède 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 . Le premier fait fonctionnent sur tous les navigateurs que j'ai testés, mais certains navigateurs mineurs ou crawlers 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 la 2ème variante n'est bien sûr pas standardisé et peut être modifié, j'ai juste choisi un nom descriptif.
Le site http_response_code()
a été introduite en PHP 5.4, et a rendu les choses plus faciles. beaucoup plus facile.
http_response_code(404);
C'est tout.
Voici une fonction que j'ai créée lorsque j'avais besoin d'une compatibilité avec une version inférieure à la 5.4 mais que je souhaitais bénéficier des fonctionnalités de la "nouvelle" version. http_response_code
fonction. Je pense que PHP 4.3 offre une compatibilité ascendante plus que suffisante, 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;
}
}
Malheureusement, j'ai trouvé que les solutions présentées par @dualed ont plusieurs défauts.
1. Utiliser substr($sapi_type, 0, 3) == 'cgi' n'est pas suffisant pour détecter les CGI rapides. Lorsque vous utilisez le gestionnaire de processus PHP-FPM FastCGI, php_sapi_name() retourne fpm et non 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 si le protocole n'est pas HTTP/1.1 (c'est-à-dire 'HTTP/1.0'). Le protocole actuel doit être détecté à l'aide de $_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 :
Pour votre référence, voici la liste complète des codes d'état des réponses HTTP (cette liste comprend des codes provenant des normes Internet de l'IETF ainsi que d'autres RFC de l'IETF. Beaucoup d'entre eux ne sont actuellement PAS supportés 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", ce qui entraînera des erreurs inattendues si vous avez, par exemple, une application client personnalisée qui appelle votre serveur et attend 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 de http_response_code() ne prend pas en charge tous les codes de réponse HTTP et peut remplacer 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 en cause mais aggrave la situation en introduisant de nouveaux bogues.
La solution de "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 rapide des CGI ne gère pas PHP-FPM. Le protocole actuel doit être détecté.
Tous les tests et commentaires sont appréciés.
Si vous êtes ici parce que Wordpress donne 404's lors du chargement de l'environnement, ceci 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û au fait qu'il envoie un Status : 404 Not Found. Vous devez le contourner. Ceci fonctionnera également :
define('WP_USE_THEMES', false);
require('../wp-blog-header.php');
header("HTTP/1.1 200 OK");
header("Status: 200 All rosy");
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.