Construire sa Première API REST avec Express.js : Routes, Requêtes et Réponses
Introduction : Les Fondations d'une API REST avec Express.js
Bienvenue dans cette leçon dédiée à la construction de votre première API RESTful. Si le terme "API REST" vous semble encore un peu abstrait, ne vous inquiétez pas ! Nous allons démystifier ce concept et le rendre très concret grâce à Express.js, un framework web minimaliste et flexible pour Node.js.
Une API (Application Programming Interface) est un ensemble de règles et de protocoles qui permettent à différentes applications de communiquer entre elles. Imaginez-la comme un menu de restaurant : il liste ce que vous pouvez commander (les fonctions disponibles) et comment le commander (les paramètres à fournir). Une API REST (Representational State Transfer) est un type spécifique d'API qui suit un ensemble de principes d'architecture pour une communication stateless et client-serveur, souvent basée sur le protocole HTTP.
Express.js est devenu le standard de facto pour le développement d'applications web et d'API REST avec Node.js. Sa simplicité, sa rapidité et son écosystème riche en font un choix excellent pour démarrer.
Dans cette leçon, nous allons explorer les piliers de toute API REST construite avec Express.js :
- Les Routes : Comment définir les points d'accès de votre API.
- Les Requêtes (
req) : Comment intercepter et comprendre ce que le client demande. - Les Réponses (
res) : Comment renvoyer des données et des statuts au client.
Préparez-vous à écrire du code et à voir votre première API prendre vie !
Prérequis
Pour suivre cette leçon, assurez-vous d'avoir les éléments suivants installés sur votre machine :
- Node.js et npm (Node Package Manager) : npm est installé automatiquement avec Node.js. Vous pouvez vérifier leur installation en ouvrant un terminal et en tapant :
node -v npm -v - Connaissances de base en JavaScript : Variables, fonctions, objets, tableaux,
const,let. - Connaissances de base du terminal/ligne de commande.
Les Fondamentaux d'Express.js pour les API REST
Avant de plonger dans le code, comprenons les concepts clés qui régissent la construction d'une API REST avec Express.js.
Le Cœur d'une API REST : Les Routes
Une route est la manière dont une application gère une requête HTTP pour un chemin (URL) et une méthode HTTP spécifiques. Elle associe une URL à une fonction JavaScript qui sera exécutée lorsque cette URL est appelée avec la méthode appropriée.
En Express.js, une route est définie comme suit :
app.METHOD(PATH, HANDLER)
app: Une instance de l'application Express.METHOD: Un verbe HTTP (GET, POST, PUT, DELETE, etc.).PATH: Le chemin URL (par exemple,/utilisateurs,/produits/:id).HANDLER: La fonction de rappel qui est exécutée lorsque la route est atteinte. Cette fonction prend généralement deux arguments :req(la requête) etres(la réponse).
Les Verbes HTTP : L'Action Derrière la Requête
Les verbes HTTP, aussi appelés méthodes HTTP, indiquent l'action que le client souhaite effectuer sur la ressource spécifiée par l'URL. Les quatre verbes les plus couramment utilisés dans une API REST sont :
GET: Utilisé pour récupérer des données du serveur. C'est une opération sûre (ne modifie pas le serveur) et idempotente (plusieurs requêtes identiques produisent le même résultat).- Exemple :
GET /articlespour obtenir tous les articles,GET /articles/123pour obtenir l'article avec l'ID 123.
- Exemple :
POST: Utilisé pour créer une nouvelle ressource sur le serveur. Les données à créer sont généralement envoyées dans le corps de la requête.- Exemple :
POST /articlespour créer un nouvel article.
- Exemple :
PUT: Utilisé pour mettre à jour une ressource existante sur le serveur, ou en créer une si elle n'existe pas. Il remplace généralement l'intégralité de la ressource.- Exemple :
PUT /articles/123pour mettre à jour l'article avec l'ID 123.
- Exemple :
DELETE: Utilisé pour supprimer une ressource du serveur.- Exemple :
DELETE /articles/123pour supprimer l'article avec l'ID 123.
- Exemple :
La Requête (req) : Interroger le Client
L'objet req (request) est une représentation de la requête HTTP entrante. Il contient toutes les informations envoyées par le client, telles que :
req.params: Capture les valeurs des segments de l'URL dynamiques.req.query: Capture les paramètres de la chaîne de requête (après?dans l'URL).req.body: Capture les données envoyées dans le corps de la requête (utile pour POST, PUT).
req.params
Utilisé pour les segments d'URL dynamiques, comme l'ID d'une ressource. Le chemin de la route est défini avec des deux-points (:).
- Exemple de route :
/utilisateurs/:id - URL appelée :
/utilisateurs/42 - Résultat dans
req.params:{ id: '42' }
req.query
Utilisé pour les paramètres optionnels passés dans l'URL après un point d'interrogation (?).
- Exemple de route :
/recherche - URL appelée :
/recherche?q=express&tri=asc - Résultat dans
req.query:{ q: 'express', tri: 'asc' }
req.body
Contient les données envoyées dans le corps de la requête HTTP, généralement pour les méthodes POST ou PUT. Pour que req.body soit correctement parsé, vous devez utiliser des middlewares Express comme express.json() pour les requêtes JSON ou express.urlencoded() pour les données de formulaire URL-encodées.
- Exemple de route :
POST /produits - Corps de la requête (JSON) :
{"nom": "Livre", "prix": 25} - Résultat dans
req.body:{ nom: 'Livre', prix: 25 }(après utilisation deexpress.json())
La Réponse (res) : Répondre au Client
L'objet res (response) est une représentation de la réponse HTTP que votre application enverra au client. Il offre plusieurs méthodes pour construire et envoyer la réponse :
res.send()
Une méthode polyvalente pour envoyer des réponses de différents types (HTML, texte, JSON, buffer). Express devine automatiquement le type de contenu.
res.send('Hello World!'): envoie du texte brut.res.send({ message: 'Objet JSON' }): envoie un objet JSON.
res.json()
Spécialement conçue pour envoyer une réponse JSON. Elle définit automatiquement l'en-tête Content-Type à application/json. C'est la méthode préférée pour les API REST.
res.json({ id: 1, nom: 'Produit A' })
res.status()
Permet de définir le code de statut HTTP de la réponse. C'est crucial pour indiquer le résultat de l'opération au client (succès, erreur, ressource non trouvée, etc.).
res.status(200): OK (succès)res.status(201): Created (ressource créée avec succès)res.status(400): Bad Request (requête mal formée)res.status(404): Not Found (ressource non trouvée)res.status(500): Internal Server Error (erreur côté serveur)
Vous pouvez chaîner res.status() avec d'autres méthodes d'envoi de réponse :
res.status(200).json({ message: 'Opération réussie' })res.status(404).send('Ressource non trouvée')
Construction de Notre Première API REST : Un Exemple Pratique
Nous allons maintenant construire une API simple pour gérer une liste de "livres". Nous implémenterons des routes pour :
- Récupérer tous les livres (
GET /livres) - Récupérer un livre par son ID (
GET /livres/:id) - Ajouter un nouveau livre (
POST /livres)
Initialisation du Projet Express.js
Créez un nouveau dossier pour votre projet et initialisez-le avec npm :
mkdir ma-premiere-api
cd ma-premiere-api
npm init -y
Installez Express.js :
npm install express
Création du Serveur Basique
Créez un fichier nommé app.js (ou server.js) à la racine de votre projet :
// app.js
// 1. Importation du module Express
const express = require('express');
// 2. Création d'une instance de l'application Express
const app = express();
// 3. Définition du port d'écoute du serveur
const PORT = 3000;
// Middleware pour parser les requêtes au format JSON
// Essentiel pour que req.body fonctionne avec les requêtes POST/PUT qui envoient du JSON
app.use(express.json());
// Données fictives (base de données temporaire en mémoire)
let livres = [
{ id: 1, titre: 'Le Seigneur des Anneaux', auteur: 'J.R.R. Tolkien' },
{ id: 2, titre: '1984', auteur: 'George Orwell' },
{ id: 3, titre: 'Fondation', auteur: 'Isaac Asimov' }
];
// --- Définition des routes de notre API ---
// Route par défaut (racine)
app.get('/', (req, res) => {
res.send('Bienvenue sur votre première API de gestion de livres !');
});
// 4. Démarrage du serveur et écoute sur le port défini
app.listen(PORT, () => {
console.log(`Serveur démarré sur http://localhost:${PORT}`);
console.log('Appuyez sur CTRL+C pour arrêter le serveur');
});
Explication du code :
const express = require('express');: Importe le module Express.const app = express();: Crée une instance de l'application Express. C'est l'objet principal avec lequel nous interagirons.const PORT = 3000;: Définit le port sur lequel notre serveur va écouter.app.use(express.json());: C'est un middleware. Il indique à Express d'analyser les corps de requêtes entrants en tant qu'objets JSON. Sans cela,req.bodyseraitundefined.let livres = [...]: Un simple tableau JavaScript pour simuler notre base de données. Dans une vraie application, ce serait une base de données comme MongoDB ou PostgreSQL.app.get('/', ...): Définit une route simple pour la racine de notre API. Quand un navigateur accède àhttp://localhost:3000/, il verra le message "Bienvenue...".app.listen(PORT, ...): Démarre le serveur Express et le fait écouter sur le port spécifié. La fonction de rappel est exécutée une fois que le serveur est prêt.
Pour lancer votre serveur, ouvrez votre terminal dans le dossier du projet et tapez :
node app.js
Vous devriez voir Serveur démarré sur http://localhost:3000 s'afficher.
Définition des Routes
Maintenant, ajoutons les routes spécifiques à nos livres dans app.js, juste avant app.listen().
Route GET : Récupérer toutes les ressources
Pour obtenir la liste de tous les livres :
// Récupérer tous les livres
// Méthode: GET
// Chemin: /livres
app.get('/livres', (req, res) => {
// res.json() envoie le tableau 'livres' en tant que réponse JSON
// Le statut 200 (OK) est implicitement envoyé par res.json() par défaut
res.json(livres);
});
Testez cette route :
Ouvrez votre navigateur ou un outil comme Postman/Insomnia/Thunder Client (extension VS Code) et naviguez vers http://localhost:3000/livres.
Vous devriez voir un tableau JSON des livres.
Route GET avec Paramètre : Récupérer une ressource spécifique
Pour obtenir un livre par son ID :
// Récupérer un livre par son ID
// Méthode: GET
// Chemin: /livres/:id (le :id est un paramètre dynamique)
app.get('/livres/:id', (req, res) => {
// req.params.id contient la valeur du segment d'URL 'id'
// Convertir l'ID en nombre car req.params.id est une chaîne
const idLivre = parseInt(req.params.id);
// Rechercher le livre dans notre tableau
const livre = livres.find(l => l.id === idLivre);
// Vérifier si le livre a été trouvé
if (livre) {
// Si trouvé, renvoyer le livre avec un statut 200 OK
res.json(livre);
} else {
// Si non trouvé, renvoyer une erreur 404 Not Found
res.status(404).json({ message: 'Livre non trouvé' });
}
});
Testez cette route :
http://localhost:3000/livres/1: devrait retourner le livre "Le Seigneur des Anneaux".http://localhost:3000/livres/99: devrait retourner{ "message": "Livre non trouvé" }avec un statut 404.
Route POST : Créer une nouvelle ressource
Pour ajouter un nouveau livre :
// Créer un nouveau livre
// Méthode: POST
// Chemin: /livres
app.post('/livres', (req, res) => {
// req.body contient les données JSON envoyées par le client (grâce à app.use(express.json()))
const nouveauLivre = req.body;
// Validation simple (ex: vérifier si titre et auteur sont présents)
if (!nouveauLivre.titre || !nouveauLivre.auteur) {
// Si les données sont incomplètes, renvoyer une erreur 400 Bad Request
return res.status(400).json({ message: 'Titre et auteur sont requis pour créer un livre.' });
}
// Assigner un nouvel ID (mécanisme simple pour l'exemple)
const newId = livres.length > 0 ? Math.max(...livres.map(l => l.id)) + 1 : 1;
nouveauLivre.id = newId;
// Ajouter le nouveau livre à notre "base de données"
livres.push(nouveauLivre);
// Renvoyer le livre créé avec un statut 201 Created
res.status(201).json(nouveauLivre);
});
Testez cette route : Vous aurez besoin d'un outil comme Postman ou Thunder Client pour envoyer une requête POST avec un corps JSON.
- Méthode :
POST - URL :
http://localhost:3000/livres - Headers :
Content-Type: application/json - Body (raw JSON) :
{ "titre": "Le Hobbit", "auteur": "J.R.R. Tolkien" }
Vous devriez recevoir en réponse le livre que vous venez d'ajouter, avec son nouvel ID, et un statut 201 Created. Si vous refaites un GET /livres, vous verrez "Le Hobbit" dans la liste.
Votre fichier app.js complet devrait ressembler à ceci :
// app.js
const express = require('express');
const app = express();
const PORT = 3000;
// Middleware pour parser les requêtes au format JSON
app.use(express.json());
// Données fictives (base de données temporaire en mémoire)
let livres = [
{ id: 1, titre: 'Le Seigneur des Anneaux', auteur: 'J.R.R. Tolkien' },
{ id: 2, titre: '1984', auteur: 'George Orwell' },
{ id: 3, titre: 'Fondation', auteur: 'Isaac Asimov' }
];
// --- Définition des routes de notre API ---
// Route par défaut (racine)
app.get('/', (req, res) => {
res.send('Bienvenue sur votre première API de gestion de livres !');
});
// GET tous les livres
app.get('/livres', (req, res) => {
res.json(livres);
});
// GET un livre par son ID
app.get('/livres/:id', (req, res) => {
const idLivre = parseInt(req.params.id);
const livre = livres.find(l => l.id === idLivre);
if (livre) {
res.json(livre);
} else {
res.status(404).json({ message: 'Livre non trouvé' });
}
});
// POST créer un nouveau livre
app.post('/livres', (req, res) => {
const nouveauLivre = req.body;
if (!nouveauLivre.titre || !nouveauLivre.auteur) {
return res.status(400).json({ message: 'Titre et auteur sont requis pour créer un livre.' });
}
const newId = livres.length > 0 ? Math.max(...livres.map(l => l.id)) + 1 : 1;
nouveauLivre.id = newId;
livres.push(nouveauLivre);
res.status(201).json(nouveauLivre);
});
// Démarrage du serveur
app.listen(PORT, () => {
console.log(`Serveur démarré sur http://localhost:${PORT}`);
console.log('Appuyez sur CTRL+C pour arrêter le serveur');
});
Conclusion et Prochaines Étapes
Félicitations ! Vous avez construit votre première API REST fonctionnelle avec Express.js. Vous avez appris à :
- Initialiser un projet Express.js.
- Définir des routes pour différents chemins et méthodes HTTP.
- Utiliser l'objet
req(requête) pour accéder aux paramètres d'URL (req.params), aux paramètres de requête (req.query), et au corps de la requête (req.body). - Utiliser l'objet
res(réponse) pour envoyer des données (res.json(),res.send()) et définir des codes de statut HTTP (res.status()).
C'est une base solide ! Dans les prochaines étapes de votre parcours de développement backend, vous explorerez des concepts plus avancés tels que :
- Gestion des erreurs : Mettre en place des middlewares pour gérer les erreurs de manière centralisée.
- Mise à jour (PUT/PATCH) et suppression (DELETE) de ressources.
- Bases de données : Connecter votre API à une base de données (MongoDB avec Mongoose, PostgreSQL avec Sequelize/Prisma, etc.) pour stocker les données de manière persistante.
- Validation des données : S'assurer que les données entrantes respectent certains formats ou contraintes.
- Authentification et autorisation : Sécuriser votre API pour que seuls les utilisateurs autorisés puissent y accéder.
- Middleware : Comprendre et créer des fonctions middleware personnalisées.
- Architecture modulaire : Organiser votre code en modules pour des projets plus importants.
Continuez à expérimenter avec les différentes méthodes HTTP et les objets req et res. La pratique est la clé pour maîtriser le développement d'API REST !