Les erreurs fatales de PHP sont renvoyées sous forme de code d'état 200 au client HTTP. Comment puis-je lui faire renvoyer un code d'état 500 (erreur de serveur interne)?
header("HTTP/1.1 500 Internal Server Error");
C'est exactement le problème que j'ai eu hier et j'ai trouvé la solution comme suit:
1) Tout d’abord, vous devez intercepter les erreurs fatales PHP, qui sont du type d’erreur E_ERROR. lorsque cette erreur se produit, le script enregistre l'erreur et met fin à l'exécution. vous pouvez obtenir l'erreur stockée en appelant la fonction error_get_last ().
2) avant la fin du script, une fonction de rappel, register_shutdown_function (), sera toujours appelée. vous devez donc enregistrer un gestionnaire d'erreurs à l'aide de cette fonction pour faire ce que vous voulez, dans ce cas, renvoyer l'en-tête 500 et une page d'erreur interne personnalisée (facultatif).
function my_error_handler()
{
$last_error = error_get_last();
if ($last_error && $last_error['type']==E_ERROR)
{
header("HTTP/1.1 500 Internal Server Error");
echo '...';//html for 500 page
}
}
register_shutdown_function('my_error_handler');
Remarque: si vous souhaitez intercepter le type d'erreur personnalisé commençant par E_USER *, vous pouvez utiliser la fonction set_error_handler () pour enregistrer le gestionnaire d'erreurs et déclencher l'erreur par la fonction trigger_error. Toutefois, ce gestionnaire d'erreurs ne peut pas gérer le type d'erreur E_ERROR. voir l'explication sur php.net à propos de gestionnaire d'erreur
J'ai utilisé "set_exception_handler" pour gérer les exceptions non capturées.
function handleException($ex) {
error_log("Uncaught exception class=" . get_class($ex) . " message=" . $ex->getMessage() . " line=" . $ex->getLine());
ob_end_clean(); # try to purge content sent so far
header('HTTP/1.1 500 Internal Server Error');
echo 'Internal error';
}
set_exception_handler('handleException');
Il n’est pas possible de manipuler PHP E_ERROR de quelque manière que ce soit, conformément à la documentation de PHP: http://www.php.net/manual/fr/function.set-error- handler.php
Il n’est pas possible non plus de traiter "E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING et la plupart des E_STRICT" en fonction de ce lien.
Vous POUVEZ fournir un gestionnaire pour l’autre erreur, avertissement et avis incluant E_USER_ERROR, mais ce n’est vraiment pas aussi utile que cela en a l’air, puisque cette erreur est renvoyée intentionnellement par le programmeur avec trigger_error ().
Et bien sûr, vous pouvez attraper n'importe quelle exception (même celles lancées par les fonctions PHP natives).
Je suis d'accord que c'est un problème. Les serveurs ne doivent PAS renvoyer 200 OK lorsque le code de l'application se bloque et se grave.
La configuration standard PHP renvoie renvoie 500 en cas d'erreur! Assurez-vous simplement que votre display_errors = off. Vous pouvez le simuler avec:
ini_set('display_errors', 0);
noFunction();
En production, la directive display_errors est désactivée par défaut.
La difficulté avec les erreurs fatales (erreurs de compilation, par exemple un point-virgule manquant) est que le script ne sera pas exécuté, il ne vous sera donc pas utile de définir le code d'état dans ce script. Toutefois, lorsque vous incluez ou exigez un script, le script d'appel est exécuté, quelles que soient les erreurs dans le script inclus. Avec cela, je viens à cette solution:
rock-solid-script.php:
// minimize changes to this script to keep it rock-solid
http_response_code(500); // PHP >= 5.4
require_once("script-i-want-to-guard-for-errors.php");
script-i-wanna-guard-for-errors.php:
// do all the processsing
// don't produce any output
// you might want to use output buffering
http_response_code(200); // PHP >= 5.4
// here you can produce the output
Dirigez votre appel vers le rock-solid-script.php et vous êtes prêt.
J'aurais mieux aimé définir le code d'état par défaut à 500 en .htaccess. Cela me semble plus élégant mais je ne trouve pas le moyen de le retirer. J'ai essayé le drapeau RewriteRule R-flag, mais cela empêche l'exécution de php, ce qui ne sert à rien.
Vous pouvez utiliser le traitement des erreurs php
N'oubliez jamais de définir header("HTTP/1.1 200 OK", true, 200);
comme dernière ligne d'un chemin d'exécution:
//first things first:
header("HTTP/1.1 500 Internal Server Error", true, 500);
//Application code, includes, requires, etc. [...]
//somewhere something happens
//die();
throw new Exception("Uncaught exception!");
//last things last, only reached if code execution was not stopped by uncaught exception or some fatal error
header("HTTP/1.1 200 OK", true, 200);
Dans PHP 5.4
, vous pouvez remplacer la fonction header
ci-dessus par la bien meilleure http_response_code(200)
ou http_response_code(500)
.
Vous devez capturer l'erreur renvoyée à l'aide de try/catch , puis utiliser ce bloc catch pour envoyer un header () avec l'erreur 500.
try {
...badcode...
throw new Exception('error');
} catch (Exception $e) {
header("Status: 500 Server Error");
var_dump($e->getMessage());
}
Si l'exception fatale n'est pas entourée de try {} blocs catch, vous devez alors inscrire un gestionnaire global et utiliser register_shutdown_function()
pour rechercher une erreur à la fin du script.