web-dev-qa-db-fra.com

Trigger 500 Internal Server Error in PHP et afficher la page d'erreur Apache

Comment puis-je déclencher 500 Erreur interne du serveur ou 404 Erreurs de page non trouvées Apache en PHP?

Pour 500 Internal Server Error, j'ai essayé le code suivant:

header("HTTP/1.0 500 Internal Server Error");

Mais cela me montre une page blanche .. Comment puis-je afficher l'erreur dans le format par défaut d'Apache?

S'il vous plaît guider ..

36
Vin

Après une telle discussion riche en connaissances, je pense qu’aucun code php ne peut afficher par défaut l’erreur 500 Internal Server Error . La solution est la suivante:
1. Créez un dossier nommé http500 à côté du fichier php.
2. Créez un fichier .htaccess et ajoutez le code suivant:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^])(.(*/
    RewriteRule ^])((a-zA
</IfModule>
  1. Code de redirection PHP: 

en-tête ('location: http500 /');

7
Vin

Vous pouvez simplement copier les documents d'erreur Apache dans votre racine Web (ou les lier symboliquement) et utiliser header() pour définir les codes d'erreur et ces documents en sortie. C'est probablement mieux, sauf si vous avez une raison impérieuse de ne pas le faire. Mais au cas où cela ne fonctionnerait pas pour vous, il y a des alternatives (bien que des alternatives hacky).

Pour 500, il suffit de mettre un bug dans votre code.

<?php throw new Exception('Nooooooooooooooo!'); ?>

Le script PHP déclenchera une exception, générant une page d'erreur Apache 500 normale. (Sachez toutefois que cela n'entraînera une erreur Apache que si le paramètre PHP init paramétré display_errors est défini sur 0. Dans la plupart des configurations de développement, ce n'est pas le cas. Si vous ne connaissez pas les paramètres de votre serveur de production, vous devrez simplement les tester pour voir s’ils fonctionnent.)

Pour 404, je pense que le mieux que vous puissiez faire est de rediriger vers une page non existante. Ce n'est pas exactement la même chose, mais pourrait le faire pour vos objectifs.

<?php header("Location: /i-dont-think-therefore-i-am-not"); ?>

Dans la plupart des navigateurs, les utilisateurs ne verront pas la redirection, ils seront simplement redirigés en silence et rapidement vers une page inexistante, ce qui provoquera une erreur Apache 404 normale. Bien sûr, l'URL aura changé et certains utilisateurs pourraient le remarquer. Si ce n'est pas acceptable, vous pouvez peut-être obtenir des résultats similaires en utilisant Apache mod_rewrite pour réécrire le backend url dans un emplacement inexistant.

Pour répondre à plusieurs commentaires: La définition du code de réponse via header() (ou d’une autre manière) n’entraînera pas le document d’erreur standard Apache. Il renverra simplement ce code de réponse avec votre propre sortie. Il s’agit d’un comportement intentionnel, conçu de manière à ce que vous puissiez avoir des documents d’erreur personnalisés ou autrement définir des codes de réponse, comme le spécifie HTTP, quelle que soit la demande. Si vous voulez les documents d'erreur Apache, vous devez soit les falsifier (selon ma suggestion initiale consistant à simplement copier les documents d'erreur à votre racine Web), soit vous devrez tromper Apache pour les renvoyer (selon ma suggestion de sauvegarde).

11
Ben Lee
function ISE()
{
  header('HTTP/1.1 500 Internal Server Error', true, 500);
  trigger_error('ISE function called.', E_USER_ERROR);//if you are logging errors?
}

Cependant, vous aurez besoin de la mise en mémoire tampon de sortie sur ON pour pouvoir utiliser la fonction php header() après avoir utilisé une fonction de sortie comme echo.

6
Etherealone

Je suis probablement assez en retard, mais cette solution devrait marcher

header("HTTP/1.0 500 Internal Server Error");
include("/path-to-public-html/errors/500.php");
die();

Cela déclenchera une réponse 500 ISE, affichera la page d'erreur 500 par défaut, puis arrêtera le script. Évidemment, vous devrez modifier l'emplacement du fichier inclus.

3
Ben Johnson mk2

vous ne pouvez tout simplement pas déclencher des pages d'erreur Apache à partir de code php sans redirection de piratage comme proposé par ben lee, car la redirection de documents d'erreur est gérée par une autre couche de la pile de votre application (plus précisément, le mod_core d'Apache).
lorsque votre script est lancé, il est trop tard.

la ruse d’obtenir une page d’erreur en lançant une exception dépend des paramètres de votre php.ini concernant gestion des erreurs et verbosité .

http_response_code()currently n'existe que dans le svn de php, il n'est donc pas disponible dans la plupart des environnements de production censés exécuter une version officielle.

mon conseil est d'implémenter correctement un gestionnaire d'erreur et d'exceptions personnalisé via set_error_handler() et set_exception_handler(), respectivement, utilisez header() pour envoyer au client les informations d'état http appropriées et (si nécessaire) générer des pages d'erreur.

2
glasz

Je sais que c'est un vieux fil cependant ...

Vous pouvez rendre un élément iframe dans votre vue, puis définir sa hauteur et sa largeur sur 100% en cas d'erreur que vous vous préparez à gérer. 

<?php header("HTTP/1.0 500 Internal Server Error"); http_response_code(500); ?>

<iframe src="page_displaying_Apache_screenshot_fullscreen.html"></iframe>

CELA DIT

Je pense vraiment que la meilleure solution moderne pour cela serait quelque chose comme: 

<?php
header("HTTP/1.0 500 Internal Server Error");
http_response_code(500);
?>
<div class="panel-body">
    <h1>Error!</h1>
     <p>
         <?php

         // Then, in the view if your in dev env, print exception and stack trace
         if ($env === 'dev') 
         {
             throw new Exception('Uh oh! Something broke while adding a new user the db.');
         }
         else 
         {
             echo "Hold your butts, an error has occured.";
             die();
         }
         ?>
     </p>
   </div>

Cela donnerait un code d'erreur approprié pour tous les utilisateurs, ainsi qu'une trace de pile pour dev si vous définissez la variable $ env sur 'dev' sur votre pile de dev .  What the user sees with this, using PHP 5.4 installed with yum using CENTOS7 by default

Pas de redirection, pas de piratage, sécurisé sauf si vous avez besoin d'exposer une erreur. :)

1
Alpha G33k

Apparemment, il existe une fonction appelée http_response_code qui vous permettra de définir le code de réponse de manière appropriée. Si cela ne fonctionne pas (la documentation indique qu'il est possible que ce soit uniquement en SVN), la fonction header peut prendre un argument de code de réponse facultatif:

header("HTTP/1.0 ...", true, 404);

Cela devrait signaler correctement Apache.

0
Cameron Skinner

Sur PHP 5.5 => "en-tête (" testeur.php ", vrai, 500);" où testeur.php n'existe pas. Cela fonctionne et me conduit à ma page 500 :)

Malheureusement, aucune des autres méthodes énumérées ici ne fonctionnait pour moi pour une raison ou une autre.

0
Gavin Simpson

Je sais que c'est un vieux fil de discussion, mais lorsque j'ai effectué une recherche sur Google, la réponse est la première. J'essayais de comprendre comment le faire ces jours-ci, alors je pense que je devrais publier ma solution de contournement à partir de 2018.

Comme vous le savez tous, non, vous ne pouvez pas simplement déclencher les pages d’erreur d’Apache à partir de PHP. Il n’ya aucun moyen de le faire. Donc, la meilleure solution que je pourrais trouver, après quelques recherches, est d'utiliser une fonction PHP pour afficher les pages d'erreur personnalisées, qui sont appelées à partir de ce que vous avez spécifié dans Apache et de la page souhaitée. pour déclencher 500 Internal Server Error.

Voici ma conf d'Apache:

ErrorDocument 400 /error.php
ErrorDocument 401 /error.php
ErrorDocument 403 /error.php
ErrorDocument 404 /error.php
ErrorDocument 500 /error.php

Comme vous pouvez le constater, toutes les erreurs 4xx et 500 sont redirigées vers le même fichier php. Pourquoi je n’utilise pas de fichiers distincts pour chaque code est une autre question, qui n’a rien à voir avec votre question ici, alors oublions cela et concentrons-nous sur error.php pour le moment.

Voici quelques lignes de error.php:

<?php
require_once("error_page.php");

$relative_path = "";
$internal_server_error = FALSE;

if (isset($_SERVER['REDIRECT_URL']) && $_SERVER['REDIRECT_URL'] != "")
{
    $relative_path = $_SERVER['REDIRECT_URL'];
    $internal_server_error = (http_response_code() >= 500);
}
else if (isset($_SERVER['REQUEST_URI']))
{
    $relative_path = $_SERVER['REQUEST_URI'];
}

ErrorPage::GenerateErrorPage($internal_server_error, $relative_path);
?>

En bref, il reçoit le code d’état HTTP d’Apache via http_response_code() et classe simplement le code d’état en deux catégories: erreur interne du serveur et erreur non interne du serveur. Il passe ensuite la catégorie à ErrorPage::GenerateErrorPage() qui génère en réalité le contenu de la page d'erreur.

Dans ErrorPage::GenerateErrorPage(), je fais quelque chose comme ceci:

<?php
http_response_code($internal_server_error ? 500 : 404);
?>

au début de la fonction, de sorte qu’il n’y ait pas d’en-têtes «déjà envoyés» gênants. Cette fonction générera une page d'erreur entièrement fonctionnelle avec le code de statut HTTP correct (ou attendu). Après avoir défini le code d’état HTTP, comme vous pouvez le deviner, un des deux contenus préparés sera généré par les codes php suivants, un pour 500, un autre pour 404.

Revenons maintenant à votre question.

Vous voulez déclencher exactement la même page d'erreur qu'Apache, et vous pouvez maintenant appeler la ErrorPage::GenerateErrorPage() de n'importe où, à condition de lui donner les paramètres corrects (TRUE pour 500, FALSE pour 404 dans mon cas).

Évidemment, comme les pages d’erreur Apache sont générées par la même fonction ErrorPage::GenerateErrorPage(), nous pouvons vous garantir que ce que vous déclenchez est exactement ce que vous attendez des pages d’erreur Apache. 

Voici mon exemple de page de déclencheur:

<?php
ob_start();

require_once("error_page.php");

try
{
    // Actual contents go here
    phpInfo();
    throw new Exception('test exception');
}
catch (Exception $e)
{
    ob_clean();
    ErrorPage::GenerateErrorPage(TRUE);
    ob_end_flush();
    exit();
}

ob_end_flush();
?>

La raison pour laquelle j’utilise ob_start() et ob_clean() est que, de cette manière, je peux effacer tout ce qui est en sortie avant que l’exception ne se produise, et envoyer une page pure de 500 Internal Server Error qui a exactement la même apparence que celle fournie par Apache la page de déclenchement (phpInfo() dans ce cas). ob_start() et ob_clean() également assurez-vous qu’il n’y aura pas d’en-têtes déjà envoyés, car rien ne sera envoyé à moins d’appeler ob_end_flush().

La solution ci-dessus est tirée de ce que j'ai étudié ces jours-ci. C’est tellement bien pour moi, mais je ne suis pas sûr que ce soit la bonne façon de le faire. Tous les commentaires, questions, réflexions, suggestions et améliorations sont les bienvenus.

0
ChenZheChina