• 50 heures
  • Difficile

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 29/07/2019

Gestion des erreurs

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Notre API se doit d'avoir une gestion des erreurs qui respecte les contraintes de REST. Depuis le début de cette partie, vous avez dû remarquer que lorsqu'une exception est lancée, une réponse HTTP formatée est renvoyée au client.

Exemple de réponse avec erreur formatée
Exemple de réponse avec erreur formatée

Comme vous pouvez le constater, un certain nombre d'informations sont données à l'utilisateur. Ces informations ne devraient pas être communiquées !

Il nous faut donc gérer les exceptions de manière à ce que le message renvoyé ne contienne que les informations nécessaires. Pour ce faire, plusieurs possibilités :

  • via la configuration, il est possible de choisir le controller appelé à chaque fois qu'une exception est lancée ;

  • via un listener, il est possible d'écouter l'évènement  kernel.exception , évènement qui est lancé à chaque fois d'une exception est lancée ;

  • via un serializer handler, un service qui se charge de formater le contenu de la réponse.

Via la configuration

Il est possible d'indiquer un code status de réponse HTTP en fonction d'un type d'exception renvoyé. Pour ce faire, c'est très simple ! ^^ Nous souhaitons faire en sorte que lorsqu'un client utilise notre API pour créer une nouvelle ressource (un article), si le JSON envoyé ne respecte pas les contraintes de validation, nous lançions une exception de typeAppBundle\Exception\ResourceValidationException, une erreur 400 (bad request) soit renvoyée avec un message formaté donnant toutes les informations nécessaires à l'utilisateur pour qu'il formate correctement le JSON envoyé.

Dans un premier temps, il faut indiquer en configuration les éléments suivants :

# app/config/config.yml

fos_rest:
    # …
    exception:
        enabled: true
        codes:
           { AppBundle\Exception\ResourceValidationException: 400 }

D'abord, nous activons le système de renvoi de réponse avec un code status donné en fonction du type d'exception renvoyée (fos_rest.exception.enabled).

Nous indiquons également dans la configuration suivante que lorsque se produit une exception de type  AppBundle\Exceptions\ResourceValidationException , une réponse avec le code status 400 sera renvoyée.

Il nous faut créer la classe d'exception ResourceValidationException. Créons donc un nouveau dossier Exception avec la classe suivante :

<?php

namespace AppBundle\Exception;

class ResourceValidationException extends \Exception
{
}

Et enfin, il nous faut maintenant adapter notre action  createAction  dans la classe de controller  ArticleController : 

<?php

namespace AppBundle\Controller;

use AppBundle\Exception\ResourceValidationException;
// …

class ArticleController extends FOSRestController
{
    /**
     * @Rest\Post("/articles")
     * @Rest\View(StatusCode = 201)
     * @ParamConverter("article", converter="fos_rest.request_body")
     */
    public function createAction(Article $article, ConstraintViolationList $violations)
    {
        if (count($violations)) {
            $message = 'The JSON sent contains invalid data. Here are the errors you need to correct: ';
            foreach ($violations as $violation) {
                $message .= sprintf("Field %s: %s ", $violation->getPropertyPath(), $violation->getMessage());
            }

            throw new ResourceValidationException($message);
        }

        // …
    }
}

Une fois le message d'erreur formaté, il suffit de lancer l'exception en question. Le FOSRestBundle se charge du reste !

Réponse formatée lorsqu'une exception de type AppBundle\Exception\ResourceValidationException
Réponse formatée lorsqu'une exception de type  AppBundle\Exception\ResourceValidationException

Et voilà le tour est joué.

Quelques petites astuces

Première astuce

Dans le cas où vous souhaiteriez configurer plusieurs exceptions avec d'autres codes status, il suffit d'en ajouter en configuration comme suit :

fos_rest:
    exception:
        enabled: true
        codes:
           { AppBundle\Exception\ResourceValidationException: 400, \Exception: 500 }
Deuxième astuce

Dans le cas où vous souhaitez créer votre propre type d'exception, il faut que votre classe étende la classe  \Exception.

Une petite dernière pour la route

Par défaut, la variable de configuration fos_rest.exception.debug a pour valeur ce qui est configuré pour l'application, en second argument du constructeur de la classeAppKernel(dans le controller frontal de l'application). Sidebugvauttrue, le message que vous indiquez à la construction de votre objet s'affichera dans la réponse HTTP. En revanche, sidebugvautfalse, le message sera toujours la transcription du code statut (dans le cas où c'est une erreur 400, le message sera "Bad Request").

Message d'erreur si la variable de configuration fos_rest.exception.debug vaut false
Message d'erreur si la variable de configuration fos_rest.exception.debug vaut false

Pour faire en sorte que le message que vous avez ajouté à votre exception s'affiche, il faut ajouter la configuration suivante :

fos_rest:
    exception:
        # …
        messages:
           { AppBundle\Exception\ResourceValidationException: true }

Pour chaque type d'exception, il faut indiquer si vous souhaitez que votre message d'erreur soit personnalisé ou non.

Via un listener 

Option 1 : écouter les évènements lancés par JMSSerializer

Comme nous l'avons vu dans le chapitre "Aller plus loin avec JMSSerializer", la librairie se charge de lancer deux évènements lors de la sérialisation (avant la sérialisation et après la sérialisation).

Il suffit donc de créer un listener sur l'un de ces évènements, et d'indiquer le type d'exception que l'on souhaite traiter pour la sérialisation.

Option 2 : écouter l'évènement  kernel.exception 

À chaque fois qu'une exception est lancée, l'évènement kernel.exception est lancé par Symfony. Il est donc tout à fait possible de créer un listener sur cet évènement et traiter l'erreur pour renvoyer une réponse formatée comme vous le souhaitez.

Rendez-vous au chapitre suivant pour suivre le Tutoriel pour la mise en place de la gestion d'erreur via un listener sur l'évènement kernel.exception.

Via un handler

La dernière possibilité est de recourir au serializer handler évoqué au chapitre "Allez plus loin avec JMSSerializer". En fonction du type d'exception, il faut simplement créer un serializer handler associé pour la sérialisation de l'objet. 

Une dernière petite chose

Peu importe la manière dont vous aller gérer vos erreurs, le plus important est de vous assurer que cela convient aux utilisateurs de votre API. Il faut indiquer le maximum d'informations, sans mettre en péril votre application. Le tout est que la réponse apportée lors d'une erreur facilite sa résolution.

Si vous connaissez personnellement (ou avez la possibilité de communiquer avec) les utilisateurs de votre API, prenez le temps de discuter et de convenir d'un format cohérent afin que vos erreurs soient traitées de la meilleure des manières.

La qualité de votre API en dépend ! ^^

Rendez-vous à la prochaine partie pour approfondir vos connaissances en matière de développement d'API Restful.

Exemple de certificat de réussite
Exemple de certificat de réussite