Vert.x : des routes et des apis

Dans le précédent article, nous avons vu comment avoir une base d'application déjà capable de servir une page de base.

Il va maintenant falloir enrichir tout ça, et je sais par avance que j'ai 2 tâches devant moi :

  1. servir un véritable frontend, de préférence une SPA avec React
  2. fournir les API pour interagir avec les données que je ne manquerai pas de manipuler

Pour faire les choses bien, commençons par le second point :)

Ajout d'une API

Ajouter une API, ça veut d'abord dire que notre serveur devra réagir différemment s'il doit servir le frontend ou s'il doit répondre à une API.

Vert.x dispose d'un système de routing pour choisir ce qui sera executé en fonction de l’adresse qui lui est demandée.

override fun start(startPromise: Promise<Void>) {
    val router: Router = Router.router(vertx)

    // Handle <server>/api/ping
    router.get("/api/ping").handler { rc: RoutingContext ->
      rc.response().end("Pong!")
    }

    // Handle <server>/api/greetings
    router.get("/api/greetings").handler { rc: RoutingContext ->
      rc.response().end("Hello from vert.x backend api!")
    }

    vertx
      .createHttpServer()
      .requestHandler (router)
      .listen(8888) { http ->
        if (http.succeeded()) {
          startPromise.complete()
          println("HTTP server started on port 8888")
        } else {
          startPromise.fail(http.cause());
        }
      }
  }

On crée donc un Router qui sera en charge de cette gestion des routes.
On indique quelles routes sont gérées et on associe un handler.
Enfin, on crée le serveur http en lui indiquant d'utiliser le router.

Vous pouvez lancer l'application et tester les accès à ces api.
Personnellement, j'utilise la commande http du package httpie sur mon Ubuntu pour ce genre de test rapide.
Pour être précis, cela donne :

❯ http :8888/api/ping
HTTP/1.1 200 OK
content-length: 5

Pong!

Le lecteur vigilant aura remarqué que je n'ai pas créé en soit une route pour le frontend. Nous verrons dans le chapitre suivant que pour le moment, l'environnement de développement fonctionnera avec le backend d'un côté et un frontend de l'autre, servi sur un autre port.
Un article ultérieur montrera comment gérer ce point en version production.

Servir le frontend

Nous allons maintenant définir un point de départ pour notre frontend.
Pour l'instant, je conserve le code du backend dans le répertoire src.

Nous allons créer le frontend  dans un répertoire subtilement nommé frontend.
Je fais le choix d'utiliser React en codant avec le langage Typescript.
Oui, c'est comme ça, je fais comme je veux :)

Pour cela, je vais suivre les explications du site React.
A la racine du projet, je lance simplement la commande :

yarn create react-app frontend --template typescript 

Pour faire simple à ce stade, j'édite directement le fichier frontend/src/app.tsx

import React, {useEffect, useState} from 'react';
import logo from './logo.svg';
import './App.css';

const App = () => {
  const [greetings, setGreetings] = useState<string>('Default before call API');
  useEffect(() => {
    console.log('Component mounted');
    fetch("/api/greetings")
      .then(res => res.text())
      .then(text => setGreetings(text))
    return () => {
      console.log('Component will be unmount');
    }
  });


  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo"/>
        <p>
          {greetings}
        </p>
      </header>
    </div>
  );
};

export default App;

J'ajoute une gestion d'un hook représentant le message de bienvenue, que l'on renseigne en appelant l'API /api/greetings définie dans notre backend.
Pour que l'ensemble fonctionne, pour le moment dans l'environnement de développement, je modifie le fichier frontend/package.json en lui ajoutant une règle lui permettant d'interroger le backend.

...
},
  "proxy": "http://localhost:8888"
}

Vous pouvez alors lancer le frontend (en n'oubliant pas de relancer le backend si vous l'aviez stoppé) :

yarn start

Vous avez maintenant une application backend, servant votre API, ainsi qu'un frontend React capable de l'interroger, accessible sur http://localhost:3000/

il reste bien des choses à faire, mais vous pouvez déjà vérifier ce que je vous propose sur le repository avec la branche vertx2.

Pour toute question, pour toute remarque, pour toute critique, vous pouvez me joindre par email ou sur Twitter.