Mettre en place une API REST 1ère partie

De plus en plus, on assiste à une demande de développement d’API REST pour communiquer avec les mobiles, ou pour communiquer entre le front et le back.

S’il est assez simple d’en coder une avec Symfony2 grâce au CRUD en renvoyant un résultat en json, ce n’est pas très souple, la validation des données doit se faire dans le contrôleur, et on doit indiquer le code d’erreur à renvoyer… heureusement pour nous, il y a FosRESTBundle pour nous aider!

Notre entité Category

Nous commençons par créer une entité catégorie simple, que nous exposerons via une API REST:

Je ne présente pas l’extension de stofDoctrineExtensions qui permet de générer un slug à la volée (entre autres, car de nombreux comportements sont possibles avec ce bundle, notamment createdAt et updatedAt).

Le composer.json

Notre entité créée et générée en base avec la commande doctrine:schema:update, nous pouvons installer FosRestBundle, JMS Serializer, Nelmio Doc, pagerFanta et le jwtAuthenticationBundle de Lexik:

AppKernel.php

N’oublions pas, dans le fichier AppKernel.php, de déclarer nos bundles:

Chaque bundle va nous être utile:

  • FosRestBundle pour mettre en place notre interface REST
  • Nelmio pour l’interface de test de notre API
  • JMS Serializer pour sérialiser les données en json ou xml
  • JWTAuthenticationBundle pour sécuriser notre API par un token

Configuration des différents bundles dans config.yml

Il y a là pas mal de configuration. Celle de FOS est vraiment bien fournie. Je vous invite à la regarder pour comprendre tous les paramètres. Vous verrez, il n’y a rien de compliqué.

Par contre, à présent que nous avons déclaré des variables pour le lexik Authentication Bundle, il faut les renseigner dans le fichier parameters.yml:

Je vous laisse bien sûr mettre la pass phrase que vous désirez. Les clefs privée et publique sont donc à placer dans le répertoire app/var/jwt/

Le routing

Pour finir, il faut déclarer dans le fichier routing.yml la route de la doc générée par nelmio:

Ainsi que la route de connexion du bundle de lexik pour obtenir le token:

Il ne reste plus qu’une chose à faire, rajouter une règle dans le vhost:

Ouf, tout est configuré, nous pouvons commencer à mettre en place le premier bundle, celui de l’authentification.

Juste avant de continuer, vous pourriez vous demander: pourquoi blog-api et non api pour le bundle nelmio? En fait, le bundle lexik d’authentification que nous allons configurer nous oblige à faire de la sorte, car il sécurise tout appel qui commence par /api, et rajouter une règle dans l’access_control n’y fait rien. Si l’on veut définir l’url api/doc, on pourra accéder à cette documentation en ligne via postman en lui passant le token d’authentification.

Le lexik Authentication Bundle

J’ai personnellement utilisé la sandbox disponible ici: https://github.com/slashfan/LexikJWTAuthenticationBundleSandbox

Ceci n’est pas du tout obligatoire. En l’état actuel des choses, vous pouvez déjà, avec Postman ou Advanced Rest Client, appeler en POST l’url http://rest-behat.local/app_dev.php/api/login_check, et vous obtiendrez quelque chose comme ça:

Ensuite, lorsque nous allons faire nos appels dans l’API, il faudra placer dans le header « Authorization Bearer le_token_genere » pour que la requête soit acceptée. Sinon, elle sera automatiquement refusée.

En utilisant la sandbox, on voit comment on peut surcharger ce bundle avec des listeners pour avoir des retours différents, plus fournis.

Par exemple, dans mon repo github, en reprenant la sandbox, j’ai un listener qui est surchargé:

Du coup, en appelant la même url, on a ce retour là:

C’est toute la beauté de la surcharge  😀

Créons notre API

C’est parti, nous savons que notre API est protégée, à présent, créons notre bundle ApiBundle dont le préfixe des routes sera API, et écrivons la fonction getCategories du contrôleur qui permet de renvoyer toutes les catégories.

  • Mon contrôleur étend le FosRestController
  • Je déclare ma route avec @Rest\Get (Rest vient des use en haut du fichier PHP)
  • J’indique à Nelmio le nom de la section, sa description, le code de retour si tout se passe bien.

Bien évidemment, getCategories n’est pas une fonction existante. Vous la trouverez dans le CategoryRepository:

A présent, si vous appelez l’url /blog-api, et que vous rentrez le token généré précédemment dans les headers de la sandbox, voici ce que vous obtenez en cliquant sur « try »:

api get categories

Mais ce n’est pas tout, vous ne voulez peut-être pas avoir de format json mais xml.

Qu’à cela ne tienne, il suffit de rajouter un nouveau header: Accept text/xml

Et vous aurez votre retour en xml! Etonnamment, cela ne fonctionne pas dans la sandbox. Pour avoir le retour en xml, vous devez mettre _format=xml dans la fenêtre Content.

Je vous mets la copie d’écran de la requête dans POSTMan REST Client

postman_categories

Dans le prochain article, nous ferons les fonctions GET (pour une catégorie), POST, PUT et DELETE.

Le code source se trouve ici: https://github.com/jpsymfony/REST-BEHAT

Rédigé par

3 comments

  1. Bonjour,

    J’ai créé le Listerner JWTResponseListener, mais ça ne change rien, je recupere juste le token, il faudrait paramétrer quelqu’un part en précisant qu’on utilise ce listener ?

    Merci

    1. Bonjour,

      Oui, tout à fait, j’aurais dû le préciser, il faut pluger ce listener comme dans la sandbox pour qu’il prenne le relais.

      Le code se trouve sur le repo: https://github.com/jpsymfony/REST-BEHAT/blob/master/src/App/ApiAuthenticationBundle/Resources/config/services.yml

      Comme tu vois, j’ai crée un ApiAuthenticationBundle que j’ai déclaré dans le AppKernel.php, et il a dedans ses services (et un routing.yml) où les listeners sont surchargés.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *