• 8 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 27/11/2023

Documentez votre API avec Nelmio

Une API, aussi bien pensée soit-elle, n’est rien sans une bonne documentation. Une option pourrait être de documenter votre API à la main. C’est tout à fait faisable, et suffisant dans de nombreux cas.

Ceci étant, la documentation étant un problème qui se pose pratiquement pour toutes les API, vous vous en doutez, un bundle existe précisément pour répondre à cette demande : Nelmio.

L’idée de ce bundle va être de générer un site web (oui oui, un site web !) qui va reprendre l’intégralité de nos routes pour les documenter, mais qui va même nous fournir un outil pour tester ces routes directement ! 

Installez Nelmio

La première étape consiste, comme toujours, à installer ce bundle :

composer require nelmio/api-doc-bundle

Pensez à accepter la recette proposée pour que les fichiers de configuration soient automatiquement créés.

Une fois Nelmio installé, le fichier nelmio_api_doc.yaml devrait avoir été créé dans le dossier routes de la configuration.

# config\routes\nelmio_api_doc.yaml

# Expose your documentation as JSON swagger compliant
app.swagger:
    path: /api/doc.json
    methods: GET
    defaults: { _controller: nelmio_api_doc.controller.swagger }

 
## Requires the Asset component and the Twig bundle
## $ composer require twig asset
app.swagger_ui:
    path: /api/doc
    methods: GET
    defaults: { _controller: nelmio_api_doc.controller.swagger_ui }

Nous allons juste décommenter les dernières lignes pour activer la route /api/doc  .

Notez le commentaire juste au-dessus qui nous précise que pour fonctionner, cette route a besoin d’installer Twig, le moteur de template. 

Installons-le :

composer require twig asset

À ce stade, la documentation existe déjà sur la route /api/doc , il nous faut juste rendre cette route accessible. En effet, dans le fichier security.yaml, nous avons dit qu’il fallait un token pour toutes les routes, sauf celle qui permet d’obtenir le token. 

Nous allons donc ajouter une seconde exception pour la route ^/api/doc, qui doit avoir un accès public :

# config\packages\security.yaml

(...)
    access_control:
        - { path: ^/api/login, roles: PUBLIC_ACCESS }
        - { path: ^/api/doc, roles: PUBLIC_ACCESS }
        - { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
(...)

Et… c’est fini, vous avez déjà une documentation !

Celle-ci sera accessible normalement à l’URL :https://127.0.0.1:8000/api/doc.

Toutes nos routes et leurs méthodes GET, POST, PUT ou DELETE sont listées dans le site web généré par Nelmio.
Nos routes sont bien visibles sur le site web généré

Nous y voyons les diverses routes disponibles, et quelle méthode HTTP doit être utilisée. 

Configurez JWT et Nelmio

Nelmio nous propose non seulement une documentation, mais ce site est également un outil pour tester nos routes comme nous le faisions avec Postman. 

En cliquant, par exemple, sur Author pour avoir la liste des auteurs, on accède à une interface qui permet d’exécuter la requête. Mais si on le fait, on se heurte à un petit souci : Erreur 401 : Pas de token JWT. 

En essayant de récupérer les livres, on obtient une erreur 401, car nous n’avons pas fourni de token, et ne sommes pas authentifiés.
Nous ne sommes pas authentifiés sur Nelmio

C’est parfaitement logique, nous n’avons pas récupéré de token. Plus encore, l’authentification étant gérée par Symfony et LexikJWTAuthenticator, nous n’avons même pas la route ici présente.

Nous allons donc expliquer à Nelmio qu’une route existe, et qu’il faut la présenter. Dans le dossier config/packages  se trouve un fichier nelmio_api_doc.yaml  qui sert précisément à cela :

# config\packages\nelmio_api_doc.yaml

nelmio_api_doc:
    documentation:
        info:
            title: Books
            description: Une API d'OpenClassrooms avec des livres, des autrices et des auteurs !
            version: 2.0.0
        paths:
            /api/login_check:
                post:
                    operationId: postCredentialsItem
                    tags:
                        - Token
                    summary: Permet d'obtenir le token JWT pour se logger.
                    requestBody:
                        description: Crée un nouveau token JWT
                        content:
                            application/json:
                                schema:
                                    $ref: '#/components/schemas/Credentials'
                    responses:
                        '200':
                            description: Récupère le token JWT
                            content:
                                application/json:
                                    schema:
                                        $ref: '#/components/schemas/Token'
        components:
            schemas:
                Token:
                    type: object
                    properties:
                        token:
                            type: string
                            readOnly: true
                Credentials:
                    type: object
                    properties:
                        username:
                            type: string
                            default: admin@bookapi.com
                        password:
                            type: string
                            default: password
            securitySchemes:
                bearerAuth:
                    type: apiKey
                    in: header
                    name: Authorization # or another header name
        security:
            - bearerAuth: []
    areas: # to filter documented areas
        path_patterns:
            - ^/api(?!/doc$) # Accepts routes under /api except /api/doc

Ce fichier précise de nombreuses choses, en particulier des informations sur l’application et la route login_check elle-même. Si vous voulez en savoir plus, comme toujours la documentation officielle sur la sécurité (en anglais)  est faite pour vous !

En bref, nous pouvons voir dans ce fichier :

  • info: cette section contient des informations générales sur notre application ;

  • path: précise la route pour réaliser la récupération de notre token et des informations de documentation (summary, requestBody, responses…) ;

  • components: décrit ce qui a été appelé dans la partie path, en particulier :

    • token: dit que l’on veut un token, chaîne de caractères, 

    • credential: précise les informations de connection (en particulier username et password),

    • securitySchemes: explique que nous voulons un champ Authorization dans le header de la requête.

Et c’est tout ! Nous pouvons maintenant tester. La première chose va être de récupérer le token, mais une nouvelle route vient d'apparaître : /api/login_check  .

On exécute le login_check sur Nelmio pour obtenir un token JWT.
La route login_check sur Nelmio

Et avec l’exécution, nous obtenons notre code :

Avec l’exécution, on reçoit un code 200 avec un token dans le Body.
La réponse nous fournit un token

Il faut maintenant spécifier ce code en cliquant sur le champ Authorize, qui est apparu tout en haut du formulaire, sans oublier, comme avec Postman, de faire précéder ce code de Bearer  :

En cliquant sur Authorize, nous renseignons “Bearer” suivi par le token dans le champ Valeur.
Nous renseignons le token

Et voilà, nous sommes désormais identifiés, et nous pouvons tester nos routes !

Améliorez les informations sur les ressources dans la documentation

Nous avons accès à nos routes, mais les commentaires sont un peu légers, les réponses possibles restent inconnues, et les paramètres difficiles à comprendre. 

Là encore, Nelmio a tout prévu, et avec quelques annotations directement dans les contrôleurs, il est possible de tout paramétrer, ou presque !

Prenons par exemple la route qui retourne l’ensemble des livres. Pour l’instant, aucune information sur la pagination n’est fournie.

Améliorons cela dans le fichier BookController.php . D’abord, nous renseignons les use  qui seront utiles pour les annotations.

<?php 
    // src\Controller\BookController.php
    // ...
    
use Nelmio\ApiDocBundle\Annotation\Model;
use Nelmio\ApiDocBundle\Annotation\Security;
use OpenApi\Annotations as OA;

Et ensuite, nous pouvons annoter chaque méthode, ici getAllBooks .

<?php 
    // src\Controller\BookController.php
    // ...
    
    /**
     * Cette méthode permet de récupérer l'ensemble des livres.
     *
     * @OA\Response(
     *     response=200,
     *     description="Retourne la liste des livres",
     *     @OA\JsonContent(
     *        type="array",
     *        @OA\Items(ref=@Model(type=Book   ::class, groups={"getBooks"}))
     *     )
     * )
     * @OA\Parameter(
     *     name="page",
     *     in="query",
     *     description="La page que l'on veut récupérer",
     *     @OA\Schema(type="int")
     * )
     *
     * @OA\Parameter(
     *     name="limit",
     *     in="query",
     *     description="Le nombre d'éléments que l'on veut récupérer",
     *     @OA\Schema(type="int")
     * )
     * @OA\Tag(name="Books")
     *
     * @param BookRepository $bookRepository
     * @param SerializerInterface $serializer
     * @param Request $request
     * @return JsonResponse
     */
    #[Route('/api/books', name: 'books', methods: ['GET'])]
    public function getAllBooks(BookRepository $bookRepository, SerializerInterface $serializer, Request $request, TagAwareCacheInterface $cache): JsonResponse
    {
        // ...

Ici sont définis les réponses (en l'occurrence, la réponse 200 ) et les paramètres disponibles (en l'occurrence, limit  et page ).

Regardons rapidement les éléments présents :

  • @OA\Response  : définit les réponses possibles (ici un code de retour200 ) :

    • @OA\JsonContent  : explique le type du contenu retourné (ici un tableau d’entité  (@model) Book ).

  • @OA\Parameter  : définit les paramètres acceptés par la méthode :

    • @OA\Schema  : le type du paramètre, ici, tout simplement un chiffre.

  •  @OA\Tag  : le groupe de la méthode, ce qui permet de classer les méthodes pour l’affichage par la suite.

Nous aurions également pu ajouter la réponse  401 Unauthorized , qui est une des réponses possibles. Cela aurait été possible en ajoutant une autre annotation  @OA\Response , comme nous l’avons fait pour le stat.

Regardons maintenant le résultat :

Quand on clique sur la route GET /api/books, nous avons deux paramètres page et limit que nous pouvons renseigner dans notre requête.
Page et limit sont bien ajoutés à la route

Nos deux nouveaux paramètres sont désormais présents. Notez également que la route a été rangée dans Books grâce au tag qui a été précisé en commentaire.

En résumé

  • La documentation est un point essentiel dans la qualité globale d’une API, et permet un meilleur taux d’adoption de l’API.

  • Nelmio est un outil qui permet de générer un site web qui documente, et même permet de tester notre application.

  • Nelmio est configurable, et permet en particulier de se connecter à JWT. 

Félicitations à nouveau, avec cette documentation votre API est désormais complète. 

Le chapitre suivant va nous permettre d’être à la fois dans la peau de l’API ET dans celle d’un client qui interroge une API.

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