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?
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?
Réponses:
Je viens de trouver cette question et j'ai pensé qu'elle avait besoin d'une réponse plus complète:
Depuis PHP 5.4, il existe trois méthodes pour y parvenir:
La header()
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");
Remarque: Selon la RFC HTTP , la raison peut être n'importe quelle chaîne personnalisée (conforme à la norme), mais pour des raisons de compatibilité client, je ne recommande pas d'y mettre une chaîne aléatoire.
Remarque: php_sapi_name()
nécessite PHP 4.0.1
Il y a évidemment quelques problèmes lors de l'utilisation de cette première variante. Le plus important dont je pense est qu'il est en partie analysé par PHP ou le serveur web et mal documenté.
Depuis 4.3, la header
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 . Le premier fait le travail sur tous les navigateurs que j'ai testé, mais certains navigateurs mineurs ou robots d' exploration Web peut 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 au 2e. La variante n'est bien sûr pas normalisée de quelque façon que ce soit et pourrait être modifiée, je viens de choisir un nom, espérons-le, descriptif.
La http_response_code()
fonction a été introduite en PHP 5.4, et cela a rendu les choses beaucoup plus faciles.
http_response_code(404);
C'est tout.
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é de la "nouvelle" http_response_code
fonction. Je crois que PHP 4.3 est plus que suffisant pour la 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;
}
}
headers_sent()
toujours vrai juste après avoir appelé header()
? (2) avez-vous déjà trouvé quelque chose comme http_response_text () dans le monde 5.4? Au moins l'ancien en-tête () peut affecter le texte après le code d'état.
headers_sent()
est vrai si vous ne pouvez plus ajouter d'en-têtes parce que le contenu a déjà été envoyé, pas si vous avez ajouté un en-tête. (2) Désolé, non. Les autres langues ont un meilleur support
http_response_code
(et peut-être plus généralement à modifier l'en-tête) ne fonctionne plus après echo
quelque chose. J'espère que ça aide.
Malheureusement, j'ai trouvé que les solutions présentées par @dualed présentaient divers défauts.
L'utilisation substr($sapi_type, 0, 3) == 'cgi'
n'est pas enogh pour détecter un CGI rapide. Lors de l'utilisation de PHP-FPM FastCGI Process Manager, php_sapi_name()
renvoie fpm pas cgi
Fasctcgi et php-fpm exposent un autre bogue mentionné par @Josh - l'utilisation header('X-PHP-Response-Code: 404', true, 404);
fonctionne correctement sous PHP-FPM (FastCGI)
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 de $_SERVER['SERVER_PROTOCOL']
(disponible depuis PHP 4.1.0
Il existe au moins 2 cas où l'appel http_response_code()
entraîne un comportement inattendu:
Pour votre référence ici, il y a la liste complète des codes d'état de réponse HTTP (cette liste comprend les codes des normes Internet IETF ainsi que d'autres RFC IETF. Beaucoup d'entre eux ne sont PAS actuellement pris en charge par la fonction PHP http_response_code de PHP): 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» entraînant des erreurs inattendues si vous avez par exemple une application cliente personnalisée qui appelle votre serveur et attend 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 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 impliqués mais aggrave les choses en introduisant de nouveaux bugs.
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 comportent é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 sur php.net:
Ajoutez cette ligne avant toute sortie du corps, dans le cas où vous n'utilisez pas la mise en mémoire tampon de sortie.
header("HTTP/1.1 200 OK");
Remplacez la partie du message («OK») par le message approprié et le code d'état par votre code, le cas échéant (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 en-tête Status: 404 Not Found. Vous devez outrepasser 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");
header("HTTP/1.1 200 OK");
http_response_code(201);
header("Status: 200 All rosy");
http_response_code (200); ne fonctionne pas car l'alerte de test 404 https://developers.google.com/speed/pagespeed/insights/
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;
}
Nous pouvons obtenir une valeur de retour différente de http_response_code via les deux environnements différents:
Dans l'environnement du serveur Web, renvoyez le code de réponse précédent si vous avez fourni un code de réponse ou si vous ne fournissez aucun code de réponse, il imprimera la valeur actuelle. La valeur par défaut est 200 (OK).
Dans CLI Environment, true sera renvoyé si vous avez fourni un code de réponse et false si vous ne fournissez aucun code de réponse.
Exemple d'environnement de serveur Web de la valeur de retour de Response_code:
var_dump(http_respone_code(500)); // int(200)
var_dump(http_response_code()); // int(500)
Exemple d'environnement CLI de la valeur de retour de Response_code:
var_dump(http_response_code()); // bool(false)
var_dump(http_response_code(501)); // bool(true)
var_dump(http_response_code()); // int(501)
header('X-PHP-Response-Code: 404', true, 404);
cela fonctionne correctement sous PHP-FPM (FastCGI)