Créer une API sous Node.js
Dans cette vidéo, on va réaliser une API, c'est-à-dire une application sur laquellle nous pourrons nous connecter, et permettre aux autres développeurs de se connecter, pour recevoir une information particulière.
L'API que l'on va créer va retourner le résultat des opérations mathématiques des utilisateurs, c'est-à-dire des additions, des soustractions, des divisions, et des multiplications. Cela nous permettra de mettre à jour la calculatrice que l'on a réalisée dans les vidéos précédentes pour ne plus calculer le résultat localement, dans le navigateur de l'utilisateur, mais le récupérer auprès de l'API.
Comme d'habitude, on va faire tout ça en JavaScript en utilisant la plateforme Node.js et l'environnement (ou framework) ExpressJS.
Vous n'avez pas besoin d'avoir vu les vidéos sur le développement de la calculatrice pour comprendre cette vidéo. Par contre, vous devriez regarder la vidéo sur la création d'un back-end sous Node.js, car je ne réexpliquerai pas les éléments que j'ai déjà traités et je me concentrerai surtout sur des choses qu'on n'a pas encore vues.
Si vous ne pouvez pas regarder la vidéo, un compte rendu est proposé plus bas.
Initialisation du projet
Pour réaliser notre API, on a besoin d'initialiser un nouveau projet et d'installer les paquets que l'on va utiliser.
Pour initialiser un projet avec les valeurs par défaut : npm init -y
Pour installer Express.js : npm install express
On peut ensuite commencer à écrire le code qui va retourner le contenu de la calculatrice lorsque l'utilisateur se rend sur la page d'accueil :
// Importe le paquet express
const express = require('express')
// Créé une application express
const app = express()
// Crée une route "/" correspondant à la racine du site.
app.get('/', (req, res) => {
// Retourne le contenu de la calculatrice
res.sendFile('/REPERTOIRE/VERS/document.html')
})
// Démarre le serveur et écoute un port donné
const PORT = 5200
app.listen(PORT, () => {
// Fonction executée lorsque l'application démarre
console.log(`Serveur démarré : http://localhost:${PORT}`)
})
On peut déjà exécuter ce code (node /chemin/api.js
) et se rendre sur http://localhost:5200/
à partir du navigateur pour vérifier que la page s'affiche correctement.
API avec paramètres
L'idée est d'ajouter quatre routes à notre API, une pour chaque opération de notre calculatrice : addition, soustraction, division et multiplication.
Chaque route acceptera un paramètre termes
qui contiendra une série de nombres à additionner, séparée par une virgule.
Par exemple la requête vers /api/addition?termes=15,20,45
devrait retourner 80.
En traduisant cette théorie dans notre code, on aurait :
// Créé route pour calculter le total d'une addition
// Exemple : /api/addition?termes=5.5,2,3
app.get('/api/addition', (req, res) => {
// Récupère les paramètres de l'adresse
const parametres = req.query
// Récupère le paramètre 'termes'
const termes = parametres.termes
if (termes == null) {
// Erreur avec code 400 (Mauvaise requête)
res.sendStatus(400)
return
}
const resultat = termes
// Sépare les valeurs
.split(',')
// Convertit chaque valeur en nombre
.map(terme => Number.parseFloat(terme))
// Retire les valeurs qui ne sont pas des nombres
.filter(nombre => isNaN(nombre) === false)
// Additionne les valeurs
.reduce((nombre, total) => total + nombre, 0)
// Retourne le résultat du calcul
res.send(resultat)
})
On peut tester ce code en utilisant notre exemple précédent : http://localhost:5200/api/addition?termes=15,20,45
Intégration de l'API
Notre calculatrice peut, à présent, être mise à jour pour ne plus calculer directement le calcul, mais appeler notre API pour obtenir le résultat.
Concrètement au lieu de faire l'addition localement :
const calculerTotal = () => {
const n1 = parseFloat(nombre1)
const n2 = parseFloat(nombre2)
switch (operation) {
case '+':
total = n1 + n2
break
}
}
On utiliser la fonction fetch
pour créer et envoyer une requête auprès de l'API :
const calculerTotal = () => {
const n1 = parseFloat(nombre1)
const n2 = parseFloat(nombre2)
switch (operation) {
case '+':
total = await fetch(`/api/addition?termes=${n1},${n2}`)
// Convertit le corps de la réponse en texte
.then(res => res.text())
// Convertit le nombre contenu dans le corps en nombre
.then(corps => Number.parseFloat(corps))
break
}
}
On peut rafraichir notre calculatrice, faire une addition et constater que le résultat est identique.
On peut aussi se rendre dans l'onglet Réseau des outils de développement du navigateur pour consulter qu'une requête a effectivement été envoyée à l'API.
API avec contenu JSON
Les termes des opérations sont, pour le moment, ajoutés à l'adresse. On peut modifier ce comportement et placer les termes dans le corps de la requête. C'est généralement ce qui est recommandé lorsqu'on transmet des informations à une API.
On peut aussi, non pas mettre les nombres directement, séparés par une virgule, mais utiliser le langage JSON, comme ca se fait habituellement. Enfin, on va changer notre requête de GET à POST, car les requêtes GET ne peuvent pas contenir d'informations dans leur corps.
Dans le code de l'API, pour accéder au contenu d'une requête, il faut traiter la requête. Pour nous faciliter la tâche, on va utiliser le paquet body-parser qui est le paquet recommandé par Express pour effectuer cette opération.
Avant de pouvoir l'utiliser, il est nécessaire de l'installer : npm install body-parser
. Il peut ensuite être intégré à la route :
const bodyParser = require('body-parser')
const jsonParser = bodyParser.json()
// Créer une route POST /api/addition
// Le contenu de la requête est au format JSON :
// Exemple : { terms: [1, 2, 3, ...] }
app.post('/api/addition',
// Récupère le contenu au format JSON de la requête
jsonParser,
// Traite la requête
(req, res) => {
// Récupère le contenu de la requête
const contenu = req.body
// Récupère le paramètres 'termes'
const termes = req.body.termes
if (termes == null) {
// Erreur avec code 400 (Mauvaise requête)
res.sendStatus(400)
return
}
// Additionne les valeurs
const resultat = termes
// Converti chaque valeur en nombre
.map(terme => Number.parseFloat(terme))
// Retire les valeurs qui ne sont pas des nombres
.filter(nombre => isNaN(nombre) === false)
// Additionne les valeurs
.reduce((nombre, total) => total + nombre, 0)
// Retourne le résultat
res.send({ resultat })
}
)
Le contenu de notre calculatrice doit aussi être adapté. La méthode de la requête ne doit plus être GET mais POST, et le contenu de la requête doit être au format JSON :
total = await fetch('/api/addition', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
termes: [n1, n2],
}),
})
.then(res => res.json())
.then(corps => corps.resultat)
Encore une fois, on peut vérifier que la requête est bien générée dans les outils de développement.
Conséquences de l'API
Nous avons vu trois façons différentes de réaliser la calculatrice :
- Sans utiliser API, où le résultat est généré localement, sur l'appareil de l'utilisateur ;
- Avec une API qui accepte et calcule le résultat de valeurs passées en paramètres de l'adresse ;
- Avec une API qui accepte et calcule le résultat de valeurs passées dans le contenu de la requête.
Lorsqu'on peut envoyer la logique de l'API à l'internaute, car elle ne prend pas beaucoup de place, ne nécessite pas de données particulières, et n'est pas confidentielle, il est préférable de le faire, car l'utilisateur peut générer le traitement sans faire de requêtes, donc sans avoir une connexion Internet et sans attendre le résultat de la requête, qui peut potentiellement prendre une ou plusieurs secondes. L'autre avantage, cette fois-ci pour l'éditeur, est que le traitement est effectué sur l'appareil de l'utilisateur et ne nécessite donc de serveur pour effectuer le calcul.
Si une API doit être faite, il est généralement préférable de passer les valeurs dans le contenu de la requête, car les paramètres des adresses sont souvent stockés dans les serveurs intermédiaires, ce qui est gênant d'un point de vue de la confidentialité, et qu'il n'est pas recommandé de mettre des données de grandes tailles dans l'adresse.
HTTPS et CORS
Deux éléments importants n'ont pas été traités dans cette vidéo : HTTPS et CORS.
Si vous réalisez une API dans des conditions réelles, vous devrez appliquer un certificat TLS sur votre serveur pour sécuriser les échanges et permettre à vos internautes d'appeler votre API.
Aussi, si les appels se font à partir d'une origine différente, c'est-à-dire un site Internet différent, vous devrez implémenter CORS, qui est un mécanisme de sécurité. Une vidéo a déjà été faite à ce sujet : La sécurité CORS