Overview

Skill Level: Beginner

Déployer une api REST PHP SLIM sur IBM Cloud

Ingredients

 

Step-by-step

  1. Base de données

    Réaliser la base de données patisserie comme indiqué dans ce mini guide :
    https://developer.ibm.com/recipes/tutorials/ibmcloud-mysql-france/

  2. Déploiement de l'API REST

    Cliquez sur le bouton Deploy to IBM Cloud. L’application va être déployer sur votre espace.
    https://github.com/cherryclass/api-gateau-slim

     

    api1

     

    Observez le fichier manifest.yml et composer.json. Toutes les dépendances vont être ajoutées lors du déploiement. Cette version de SLIM fonctionne uniquement avec PHP 7, IBM Cloud déploie pour le moment PHP 5. Il faut donc le spécifier dans composer.json.

    L’application ne fonctionnera pas tant que le service de base de données de l’étape 1 n’est pas relié. 
    Dans le tableau de bord, cliquer sur l’api correspondante, puis sur connexions, créer une connexion. Ajouter le service Mysql avec connect et reconstituer.

    On récupere automatiquement les identifiants dans l’application. Vous pouvez observer la fonction connexion dans index.php.

    Il est possible de lier au déploiement le service par la modification des lignes de commentaires dans le manifest.yml de l’application avec le nom de votre service, affiché dans le tableau de bord.

     

  3. Test de l'application

    Testez l’URI gateau/8 de votre application. Attention à bien remplacer l’url de l’application par la votre.
    Exemple “http://api-gateau-palest-firetrap.mybluemix.net/gateau/8” 

    On pourra la tester directement via le navigateur puisque c’est une URI avec une méthode GET. On pourra également tester les URI avec REASTEASY ou POSTMAN.

    Le serveur renvoie les éléments en JSON.

    api2

  4. Déploiement du client

    Cette étape peut être testée directement sur votre poste, puisque le client n’utilise que du HTML et du Javascript. Il se connecte via AJAX au serveur.

    Téléchargez les fichiers du dépôt suivant :
    https://github.com/cherryclass/cli-gateau

    Modifiez la variable serveur de index.js avec l’URL correspondante de l’étape 2.
    Testez directement index.html sur votre poste, aucun serveur web n’est nécessaire.

     

    api3

     

    Déployez l’application grâce à la commande :

     bx cf push

    Si vous ne savez pas comment déployer une application en ligne de commande, rendez-vous ici :
    https://developer.ibm.com/recipes/tutorials/ibmcloud-application-en-ligne-de-commande/

  5. Documentation et scalabilité

    Ajoutez le service auto-scaling à votre application.
    Ajoutez le service API Connect.

    Dans API Connect, séléctionnez “importer l’api à partir d’un fichier ou d’une URL”, séléctionnez URL puis ajoutez l’URL de votre application en ajoutant swagger.php de la forme :
    https://api-gateau.mybluemix.net/swagger.php

    Validez en haut à droite, puis cliquez sur Explorer, brouillons en haut à droite. On peut observer les différentes URI, les paramètres etc. Ceci est obtenu par la génération d’un fichier Swagger en JSON.

    api4

  6. Authentification

    Nous allons utiliser les JSON Web Tokens de Firebase: https://jwt.io/
    Ce package est déjà installé dans cette application. On implémente deux URI :

    • token pour obtenir un token en fonction d’un mot de passe

    En cas de mot de passe correct, on retourne un token et un statut http valide, sinon un statut http unauthorized

    • validetoken indique si le token est valide

    En cas de token valide, on retourne un statut http valide, sinon unauthorized

     

    /**
    * @SWG\Get(
    * path="/token",
    * tags={"user"},
    * summary="Return a token",
    * description="Return a token",
    * @SWG\Parameter(
    * name="pass",
    * in="header",
    * required=true,
    * type="string"
    * ),
    * @SWG\Response(
    * response=200,
    * description="successful operation",
    * @SWG\Schema(
    * type="object"
    * )),
    @SWG\Response(
    * response=401,
    * description="unauthorized",
    *
    * ))
    */
    $app->get('/token', function(Request $request, Response $response){
    $pass = $request->getQueryParam('pass');
    $allowed= ckeckPass($pass);
    if($allowed){
    $token=getTokenJWT();
    return $response->withJson($token,200);
    }else{
    return $response->withStatus(401);
    }
    });


    /**
    * @SWG\get(
    * path="/validetoken",
    * tags={"user"},
    * summary="Test a token",
    * description="Test a token",
    * @SWG\Parameter(
    * name="token",
    * in="header",
    * required=true,
    * type="string"
    * ),
    * @SWG\Response(
    * response=200,
    * description="successful operation",
    *
    * ),
    * @SWG\Response(
    * response=401,
    * description="unauthorized"
    *
    * )
    * )
    * )
    */
    $app->get('/validetoken', function(Request $request, Response $response){
    $token = $request->getQueryParam('token');
    if(validJWT($token)){
    return $response = $response->withStatus(200);
    }else{
    return $response = $response->withStatus(401);
    }
    });

     

     

    Voici les fonctions ckeckPassgetTokenJWT et validJWT. Il est préférable d’indiquer sa propre clef secrete.

     

     function getTokenJWT() {
    //30 min
    payload = array("exp" => time() + (60 * 30));
    return JWT::encode($payload, "myOwnKey");
    }
    function ckeckPass($pass){
    //$configs = include('config.php');
    //$sitepass=$configs["sitepass"];
    $sitepass="mypass";
    return (strcmp($sitepass,$pass)==0);
    }
    function validJWT($token) {
    $res = false;
    try {
    $decoded = JWT::decode($token, "superKey", array('HS256'));
    $res = true;
    } catch (Exception $e) {}
    return $res;
    }

     

     

    N’oubliez pas de tester ces URI avec REASTEASY. On peut modifier cette solution par un test selon login/mdp et un temps de jeton differencié selon le groupe de l’utilisateur.

    Modifiez les paramètres de l’URI gateau en POST qui permet d’ajouter un gateau. Cette URI doit tenir compte du token.

     

    $token = $request->getQueryParam('token');
    if(validJWT($token)){
    //insertion du gateau
    return $response->withStatus(200);
    }else{
    return $response->withStatus(401);
    }

     

    Modifiez le client en ajoutant une étape de saisie de mot de passe et récupération de token.

     

    $( "#btn-valide").click(function(event) {
    $.ajax({
    type: "GET",
    url: urlServeur+"/token",
    data: "pass="+ $("#password").val(),
    success: function(data){
    sessionStorage.setItem('token', data);
    //renvoie vers une autre page ou modification du contenu de la page en cours au choix
    window.location.href = "secondepage.html";
    },
    error: function(XMLHttpRequest, textStatus, errorThrown) {
    //on indique avec bootsrap une erreur sur le mot de passe
    $(".form-group-password").addClass("has-danger");
    $("#password").addClass("form-control-danger");
    }
    });
    });

     

     

    Puis pour l’enregistrement d’un gateau, n’oubliez pas de renvoyer le token.

     

    var htmlSession="<div class='container section2'><p> Session expirée <div class='offset-5 col-3'> 
    <a class='btn btn-danger' href='index.php' role='button'>Page principale</a> </div> </p> </div> ";
    var token=sessionStorage.getItem('token');
    $.ajax({
    type: "POST",
    contentType: 'application/json; charset=utf-8',
    url: urlServeur+"/gateau/"+id+"?token="+token,
    success: function(data){
    //gateau inseré
    },
    error: function(XMLHttpRequest, textStatus, errorThrown) {
    //erreur, mauvais token ou probleme à l'insertion à gérer selon le code HTTP !
    }
    });
  7. Exercices

    Implementez les URI suivantes en choisissant judicieusement la méthode :

    • gateaux qui permet d’afficher tous les gateaux
    • gateau/{id} qui supprime un gateau en fonction de son id avec gestion du jeton
    • gateau/{id} qui modifie le nom d’un gateau en fonction de son id avec gestion du jeton

     

     

  8. Serverless

     ************   A venir  *************

  9. Kits de démarrage web

    Je vous invite à tester les kits de démarrage des applications web. Il n’y a pour le moment pas de kit avec PHP mais Express.js et Flask par exemple.

  10. What else ?

    Ces tutoriels peuvent vous intéresser :
    https://developer.ibm.com/recipes/author/l-frebourg/

Join The Discussion