Section courante

A propos

Section administrative du site

Gestionnaire d'erreurs

Toute application sera confrontée à une situation dans laquelle un problème se produit et nous ne pouvons pas fournir de solution autre que d'en informer l'utilisateur. Par exemple, l'utilisateur essaie de récupérer une ressource inexistante.

Gestion des exceptions

Dans une application Web créée avec Fano Framework, toutes les exceptions non gérées étant générées seront gérées par l'instance d'interface IErrorHandler.

Cette interface possède une méthode :

  1. Function handleError(
  2.     Const env:ICGIEnvironmentEnumerator;
  3.     Const exc:Exception;
  4.     Const status:Integer=500;
  5.     Const msg:String ='Erreur interne du serveur'
  6. ):IErrorHandler;

Paramètres

Paramètre Description
env Est un énumérateur de variables d'environnement.
exc Est une instance d'exception à gérer.
status Est la valeur entière du code HTTP à envoyer au client.
msg Est la valeur de chaîne du message HTTP à envoyer au client.

Les gestionnaires d'erreurs sont enregistrés dans la méthode buildErrorHandler() du fournisseur de services d'application, comme indiqué dans l'exemple de code ci-dessous.

Exceptions

Le Fano Framework définit certaines classes d'exceptions correspondant au code d'erreur HTTP :

Classe Message d'erreur Description
EBadRequest HTTP 400 Bad Request. Ce code d'erreur permet d'indiquer qu'une mauvaise requête est envoyé à la page.
EUnauthorized HTTP 401 Unauthorized. Ce code d'erreur permet d'indiquer qu'une autorisation est requise pour cette page.
EForbidden HTTP 403 Forbidden Ce code d'erreur permet d'indiquer que l'accès à cette page est refusé.
ENotFound HTTP 404 Not Found. Le code d'erreur 404 permet d'indiquer permet d'indiquer que la page Web ou le fichier est introuvable.
EMethodNotAllowed HTTP 405 Method Not Allowed. Ce message d'erreur permet d'indiquer que les méthodes HTTP utiliser pour l'action au serveur Web n'est pas autorisé.
ENotAcceptable HTTP 406 Not Acceptable. Ce message d'erreur permet d'indiquer que les données ou le nom de la page n'est pas acceptable sur le serveur Apache.
EGone HTTP 410 Gone. Ce code d'erreur permet d'indiquer que la page est partie.
EUnsupportedMediaType HTTP 415 Unsupported Media Type. Ce code d'erreur permet d'indiquer que le type de support de média n'est pas supporté par la page.
EUnprocessableEntity HTTP 422 Unprocessable Entity. Ce code d'erreur permet d'indiquer une entité ne pouvant être un processus d'une page.
ETooManyRequest HTTP 429 Too Many Request. Ce code d'erreur permet d'indiquer que le client (généralement défini par l'adresse IP) a envoyé trop de demandes au cours d'une période donnée.
EInternalServerError HTTP 500 Internal Server Error. Cette erreur permet d'indiquer qu'une erreur interne du serveur Web empêche de retourner la page.
ENotImplemented HTTP 501 Not Implemented. Ce code d'erreur permet d'indiquer que la méthode n'est pas mise en oeuvre.
EBadGateway HTTP 502 Bad Gateway. Ce code d'erreur permet d'indiquer que la méthode n'est pas mise en oeuvre.
EServiceUnavailable HTTP 503 Service Unavailable. Ce code d'erreur permet d'indiquer que le serveur est temporairement non-disponible.
EGatewayTimeout HTTP 504 Gateway Timeout. Ce code d'erreur permet d'indiquer que le délai est dépassé sur le chemin du réseau.

Si vous déclenchez l'une des exceptions ci-dessus, Fano Framework renvoie son erreur HTTP correspondante en réponse. Toutes les classes d'exception ci-dessus sont dérivées de la classe EHttpException.

Le Fano Framework définit également d'autres exceptions non liées au code d'erreur HTTP. Chacune de ces exceptions entraînera une réponse d'erreur HTTP 500, à l'exception de ERouteHandlerNotFound entraînant une erreur HTTP 404.

Implémentation du gestionnaire d'erreurs intégré

Le Fano Framework est fourni avec plusieurs implémentations IErrorHandler :

Implémentation Description
TFancyErrorHandler Gestionnaire d'erreurs de base par défaut générant l'erreur dans un code HTML thématique. Vous l'utilisez principalement à des fins de développement car il affiche des informations d'erreur détaillées.
TErrorHandler Gestionnaire d'erreurs de base générant l'erreur au format HTML simple. Vous l'utilisez principalement à des fins de développement car il affiche des informations d'erreur détaillées.
TAjaxErrorHandler Gestionnaire d'erreurs générant des informations d'erreur au format JSON.
TNullErrorHandler Gestionnaire d'erreurs ne générant rien d'autre qu'une erreur HTTP.
THtmlAjaxErrorHandler Gestionnaire d'erreurs composite générant une erreur HTML de base ou JSON selon que la demande est AJAX ou non.
TLogErrorHandler Gestionnaire d'erreurs enregistrant les informations d'erreur au lieu de les transmettre au client.
TLoggerErrorHandler Gestionnaire d'erreurs similaire à TLogErrorHandler, sauf qu'il peut déterminer le niveau de journalisation à enregistrer. Par exemple, il peut enregistrer uniquement les journaux de type critique.
TTemplateErrorHandler Gestionnaire d'erreurs générant une erreur à l'aide d'un gabarit HTML. Cette classe est fournie pour permettre au développeur d'afficher une page d'erreur bien formatée. Pour une configuration de production, c'est principalement ce que vous utilisez.
TCompositeErrorHandler Gestionnaire d'erreurs composé de deux autres gestionnaires d'erreurs. Il est fourni pour combiner, par exemple, l'enregistrement des erreurs dans un fichier et l'affichage d'une sortie bien formatée sur le client. Pour combiner trois gestionnaires d'erreurs ou plus, vous devez les connecter en guirlande.
TGroupErrorHandler Gestionnaire d'erreurs composé d'un ou plusieurs gestionnaires d'erreurs. Il est similaire au gestionnaire d'erreurs composite ci-dessus, sauf qu'il est plus flexible car vous pouvez composer un nombre arbitraire de gestionnaires d'erreurs.
TDecoratorErrorHandler Gestionnaire d'erreurs abstrait qui décore un autre gestionnaire d'erreurs.
TConditionalErrorHandler Gestionnaire d'erreurs abstrait sélectionnant l'un des deux gestionnaires d'erreurs en fonction d'une condition. Le descendant doit implémenter sa méthode abstraite condition().
TBoolErrorHandler Gestionnaire d'erreurs sélectionnant l'un des deux gestionnaires d'erreurs en fonction d'une condition spécifiée dans le paramètre du constructeur.
TNotFoundErrorHandler Gestionnaire d'erreurs sélectionnant l'un des deux gestionnaires d'erreurs en fonction d'une condition si l'exception est ERouteHandlerNotFound. Cela vous permet de gérer l'erreur HTTP 404 séparément, par exemple pour afficher un gabarit HTML différent pour l'erreur HTTP 404.
TMethodNotAllowedErrorHandler Gestionnaire d'erreurs sélectionnant l'un des deux gestionnaires d'erreurs en fonction d'une condition si l'exception est EMethodNotAllowed. Cela vous permet de gérer l'erreur HTTP 405 séparément, par exemple pour utiliser un gabarit HTML différent pour l'erreur HTTP 405.
TInternalServerErrorHandler Gestionnaire d'erreurs sélectionnant l'un des deux gestionnaires d'erreurs en fonction d'une condition si l'exception est EInternalServerError. Cela vous permet de gérer les erreurs HTTP 500 séparément, par exemple pour utiliser un gabarit HTML différent pour les erreurs HTTP 500.

Afficher un message d'erreur détaillé

TFancyErrorHandler et TErrorHandler sont des implémentations de base d'IErrorHandler, affichant des informations d'erreur de base dans le type de contenu HTML, telles que le type d'exception déclenchée, le message d'exception et les variables d'environnement et de trace de pile.

Si vous compilez une application avec des informations de débogage telles que le drapeau -g ou -gh, la trace de pile est assez détaillée, comme le numéro de ligne dans le fichier source. Sans informations de débogage, elle affiche uniquement l'emplacement de la mémoire.

Par défaut, lorsque vous héritez du fournisseur de services d'application de TBasicAppServiceProvider, vous utilisez le gestionnaire d'erreurs TFancyErrorHandler.

  1. Type
  2.  TAppServiceProvider=Class(TBasicAppServiceProvider)
  3.   Public
  4.    Procedure register(Const Container:IDependencyContainer); override;
  5.  End;

Pour enregistrer un type de gestionnaire d'erreurs différent, vous devez remplacer la méthode buildErrorHandler().

Afficher un message d'erreur détaillé au format JSON

  1. Type
  2.  TAppServiceProvider=Class(TBasicAppServiceProvider)
  3.   Protected
  4.         Function buildErrorHandler(
  5.             Const ctnr:IDependencyContainer;
  6.             Const config:IAppConfiguration
  7.         ):IErrorHandler; override;
  8.         ...
  9.  End;
  10. ...
  11.  
  12.  Function TAppServiceProvider.buildErrorHandler(
  13.         Const ctnr:IDependencyContainer;
  14.         Const config:IAppConfiguration
  15.     ) : IErrorHandler;
  16.  Begin
  17.   Result:=TAjaxErrorHandler.create();
  18.  End;

Masquer le message d'erreur

  1. Function TAppServiceProvider.buildErrorHandler(
  2.     Const ctnr:IDependencyContainer;
  3.     Const config:IAppConfiguration
  4. ):IErrorHandler;
  5. Begin
  6.  Result:=TNullErrorHandler.create();
  7. End;

Erreur d'affichage avec le gabarit HTML

  1. Function TAppServiceProvider.buildErrorHandler(
  2.     Const ctnr:IDependencyContainer;
  3.     Const config:IAppConfiguration
  4. ):IErrorHandler;
  5. Begin
  6.  Result:=TTemplateErrorHandler.create('/path/to/error/template.html');
  7. End;

Enregistrer l'erreur dans le fichier

  1. Function TAppServiceProvider.buildErrorHandler(
  2.     Const ctnr:IDependencyContainer;
  3.     Const config:IAppConfiguration
  4. ):IErrorHandler;
  5. Begin
  6.  Result:=TLogErrorHandler.create(TFileLogger.create('/path/to/log/file'));
  7. End;

Vous devez vous assurer que /path/to/log/file est accessible en écriture.

Ou si vous souhaitez enregistrer uniquement les messages d'urgence et critiques, utilisez plutôt TLoggerErrorHandler.

  1. Function TAppServiceProvider.buildErrorHandler(
  2.     Const ctnr:IDependencyContainer;
  3.     Const config:IAppConfiguration
  4. ):IErrorHandler;
  5. Begin
  6.     Result:=TLoggerErrorHandler.create(
  7.         TFileLogger.create('/path/to/log/file'),
  8.         [logEmergency,logCritical]
  9.     );
  10. End;

Enregistrer l'erreur dans un fichier et afficher l'erreur à partir du modèle

Utilisez TCompositeErrorHandler ou TGroupErrorHandler pour composer plusieurs gestionnaires d'erreurs en un seul.

  1. Function TAppServiceProvider.buildErrorHandler(
  2.     Const ctnr:IDependencyContainer;
  3.     Const config:IAppConfiguration
  4. ):IErrorHandler;
  5. Begin
  6.  Result:=TCompositeErrorHandler.create(
  7.         TLogErrorHandler.create(TFileLogger.create('/path/to/log/file')),
  8.         TTemplateErrorHandler.create('/path/to/error/template.html')
  9.     );
  10. End;

ou avec TGroupErrorHandler :

  1. Function TAppServiceProvider.buildErrorHandler(
  2.     Const ctnr:IDependencyContainer;
  3.     Const config:IAppConfiguration
  4. ):IErrorHandler;
  5. Begin
  6.     Result:=TGroupErrorHandler.create([
  7.         TLogErrorHandler.create(TFileLogger.create('/path/to/log/file')),
  8.         TTemplateErrorHandler.create('/path/to/error/template.html')
  9.     ]);
  10. End;

Enregistrer l'erreur dans un fichier et afficher une page d'erreur vide

  1. Function TAppServiceProvider.buildErrorHandler(
  2.     const ctnr:IDependencyContainer;
  3.     const config:IAppConfiguration
  4. ):IErrorHandler;
  5. Begin
  6.     Result:=TCompositeErrorHandler.create(
  7.         TLogErrorHandler.create(TFileLogger.create('/path/to/log/file')),
  8.         TNullErrorHandler.create()
  9.     );
  10. End;

Composer plusieurs gestionnaires d'erreurs

Utilisez TCompositeErrorHandler avec la connexion en guirlande ou TGroupErrorHandler pour composer plusieurs gestionnaires d'erreurs en un seul.

  1. Function TAppServiceProvider.buildErrorHandler(
  2.     Const ctnr:IDependencyContainer;
  3.     Const config:IAppConfiguration
  4. ):IErrorHandler;
  5. Begin
  6.  Result:=TCompositeErrorHandler.create(
  7.         TCompositeErrorHandler.create(
  8.             //Journal dans un fichier et STDERR
  9.             TLogErrorHandler.create(TFileLogger.create('/path/to/log/file')),
  10.             TLogErrorHandler.create(TStdErrLogger.create())
  11.         ),
  12.         TTemplateErrorHandler.create('/path/to/error/template.html')
  13.     );
  14. End;

ou avec TGroupErrorHandler

  1. Function TAppServiceProvider.buildErrorHandler(
  2.     Const ctnr:IDependencyContainer;
  3.     Const config:IAppConfiguration
  4. ) : IErrorHandler;
  5. Begin
  6.     //enregistrer l'erreur dans le fichier et STDERR et afficher également le modèle d'erreur
  7.     Result:=TGroupErrorHandler.create([
  8.         TLogErrorHandler.create(TFileLogger.create('/path/to/log/file')),
  9.         TLogErrorHandler.create(TStdErrLogger.create()),
  10.         TTemplateErrorHandler.create('/path/to/error/template.html')
  11.     ]);
  12. End;

Sélectionnez un gestionnaire d'erreurs différent en fonction de la configuration de production ou de développement

  1. Function TAppServiceProvider.buildErrorHandler(
  2.     Const ctnr:IDependencyContainer;
  3.     Const config:IAppConfiguration
  4. ):IErrorHandler;
  5. Var prodErrHandler:IErrorHandler;
  6.     devErrHandler:IErrorHandler;
  7.     isProd:Boolean;
  8. Begin
  9.     prodErrHandler:=TCompositeErrorHandler.create(
  10.         TLogErrorHandler.create(TFileLogger.create('/path/to/log/file')),
  11.         TTemplateErrorHandler.create('/path/to/error/template.html')
  12.     );
  13.     devErrHandler:=TErrorHandler.create();
  14.     isProd:=config.getBool('isProduction');
  15.     result:=TBoolErrorHandler.create(
  16.         prodErrHandler,
  17.         devErrHandler,
  18.         isProd
  19.     );
  20. End;

Créez votre propre gestionnaire d'erreurs

Si vous trouvez que les gestionnaires d'erreurs intégrés ne suffisent pas pour votre cas d'utilisation, vous pouvez créer votre propre implémentation IErrorHandler.

  1. Unit myerrorhandler;
  2.  
  3. INTERFACE
  4.  
  5. {$MODE OBJFPC}
  6. {$H+}
  7.  
  8. Uses
  9.     fano;
  10.  
  11. Type
  12.     TMyErrorHandler=Class(TInterfacedObject,IErrorHandler)
  13.      Public
  14.         Function handleError(
  15.             Const env:ICGIEnvironmentEnumerator;
  16.             Const exc:Exception;
  17.             Const status:Integer=500;
  18.             Const msg:String ='Erreur interne du serveur'
  19.         ) : IErrorHandler;
  20.     end;
  21.  
  22. IMPLEMENTATION
  23.  
  24.     Function TMyErrorHandler.handleError(
  25.         Const env:ICGIEnvironmentEnumerator;
  26.         Const exc:Exception;
  27.         Const status:Integer=500;
  28.         Const msg:String ='Erreur interne du serveur'
  29.     ):IErrorHandler;
  30.     Begin
  31.         Writeln('Content-Type: text/html');
  32.         Writeln('Status: ', status, ' ', msg) ;
  33.         Writeln();
  34.         Writeln('Message d'erreur bizarre');
  35.         Result:=self;
  36.     End;
  37.  
  38. END.

Les lignes suivantes sont obligatoires pour se conformer au protocole CGI :

  1. WriteLn('Content-Type: text/html');
  2. WriteLn('État: ',status,' ',msg);
  3. WriteLn();

Pour utiliser votre propre gestionnaire d'erreurs :

  1. Uses
  2.     fano,
  3.     myerrorhandler;
  4.  
  5. Function TAppServiceProvider.buildErrorHandler(
  6.     Const ctnr:IDependencyContainer;
  7.     Const config:IAppConfiguration
  8. ):IErrorHandler;
  9. Begin
  10.     Result:=TMyErrorHandler.create();
  11. End;


Dernière mise à jour : Vendredi, le 18 octobre 2024