API REST & HTTP
Qu'est-ce qu'une API ?
Une API (Application Programming Interface) est une interface qui permet à deux applications de communiquer entre elles via des règles et des conventions standardisées.
Analogie simple :
- Un restaurant : Vous consultez le menu (documentation API), passez commande au serveur (requête), et recevez votre plat (réponse)
- Le serveur = l'API
- La cuisine = le serveur backend
- Vous = le client (application web, mobile, etc.)
REST API : Les principes
REST (Representational State Transfer) est un style architectural pour concevoir des API web.
Les 6 principes REST
- Architecture Client-Serveur
- Séparation entre interface utilisateur (client) et stockage de données (serveur)
- Sans état (Stateless)
- Chaque requête contient toutes les informations nécessaires
- Le serveur ne garde pas de "session"
- Cacheable
- Les réponses indiquent si elles peuvent être mises en cache
- Interface uniforme
- URLs cohérentes et prévisibles
- Système en couches
- Le client ne sait pas s'il parle directement au serveur ou à un intermédiaire
- Code à la demande (optionnel)
- Le serveur peut envoyer du code exécutable (JavaScript)
HTTP
À chaque fois que vous tentez d'accéder à une page web vous réalisez une requête HTTP. Cette requête va contacter l'hébergeur de la page que vous ciblez et va attendre une réponse qui permettra l'affichage du site. Il est important de comprendre que lorsque vous cherchez à accéder à un site, pour chaque fichier requis vous réaliserez une requête HTTP pour obtenir l'information. Les gros sites pouvant rapidement atteindre des masses critiques de requêtes, il est important pour eux d'optimiser les appels HTTP au maximum afin de gagner en performances.
Types de requête
Lorsque vous réalisez une requête HTTP elle possède un type. Par défaut il s'agit d'une requête GET. Elle permet
d'obtenir des informations en les ramenant au client. Mais il existe de nombreux autres types, dont voici une liste des
plus fréquemment rencontrés.
POST: Il s'agit de la requête par défaut lorsque l'on veut envoyer des données au serveur, lors d'une création ou de la soumission d'un formulaire par exemple.DELETE: La requête utilisée pour indiquer la suppression/destruction de données.PATCH: Requête utile en cas de modification de données.HEAD: permet de ne récupérer que les informations d'en-tête et donc de limiter la taille de la réponse. Utile lorsque l'on souhaite faire des vérifications avant une requête GET par exemple pour connaître la taille de la page en amont.
Codes HTTP
Une fois la réponse reçue, elle est souvent accompagnée d'un code qui permet de rapidement savoir la nature de la
réponse. Vous connaissez sûrement l'un des plus connus : le code 404 Not Found. Les codes HTTP se décomposent d'abord
avec leur chiffre de centaine qui correspond chacun à un type. Par exemple, le 4 de 400 ici correspond à une erreur
client. Et ensuite, on incrémente un nombre pour avoir du détail, ici 04 pour dire ressource non trouvée (not found).
| Code | Signification | Description |
|---|---|---|
| 200 | OK | La requête a été traitée avec succès. Cela signifie généralement que la requête a réussi et que la réponse contient les données demandées. |
| 201 | Created | La requête a été traitée avec succès, et une nouvelle ressource a été créée. Ceci est couramment utilisé pour les requêtes POST. |
| 204 | No Content | La requête a réussi, mais il n'y a pas de contenu à renvoyer. Par exemple, après une suppression (DELETE), la réponse peut être vide. |
| 400 | Bad Request | La requête est mal formulée ou manque d'informations nécessaires. Ce code indique généralement une erreur du côté du client. |
| 401 | Unauthorized | La requête nécessite une authentification. Ce code est souvent renvoyé lorsqu'une API requiert une clé d'API ou un jeton d'authentification. |
| 403 | Forbidden | Le serveur comprend la requête, mais il refuse de l'exécuter. Cela peut être dû à des permissions insuffisantes. |
| 404 | Not Found | La ressource demandée n'a pas été trouvée sur le serveur. Cela est couramment utilisé pour indiquer que l'URL ou l'endpoint n'existe pas. |
| 405 | Method Not Allowed | La méthode HTTP utilisée (par exemple, GET, POST, PUT, DELETE) n'est pas autorisée pour la ressource spécifiée. |
| 500 | Internal Server Error | Il y a une erreur côté serveur. Cela signifie que quelque chose s'est mal passé, mais le serveur ne peut pas donner plus de détails. |
Vous trouverez le détail des codes HTTP ici.
Réaliser une requête HTTP en NodeJS
Le but d'une API Node.js est de pouvoir répondre à des requêtes HTTP. Pour ce faire, nous allons utiliser le package natif
de Node.js http. Ce package nous permet de créer un serveur HTTP et de répondre à des requêtes. Nous avons déjà vu
comment créer le serveur et l'écouter. Maintenant, j'aimerais qu'il soit capable de créer des réponses en fonction du type
de requête.
Ce package étant natif à Node.js, il n'est pas nécessaire de l'installer.
Pour ce faire, nous allons récupérer l'objet req qui est passé en paramètre de notre callback de création de serveur.
Cet objet contient de nombreuses informations sur la requête, dont la méthode utilisée. Nous allons donc vérifier la
méthode de la requête et renvoyer une réponse en fonction via l'objet res.
import http from 'http'
// Création du serveur HTTP
const server = http.createServer((req, res) => {
// Récupération de l'URL et de la méthode de la requête
const url = req.url
const method = req.method
// Gestion de la route /users
if (url === '/users' && method === 'GET') {
// Simulation d'une liste d'utilisateurs
res.writeHead(200, { 'Content-Type': 'application/json' })
res.end(
JSON.stringify([
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' },
]),
)
}
// Gestion de la route /users/:id pour obtenir un utilisateur spécifique
else if (url?.startsWith('/users/') && method === 'GET') {
const userId = url.split('/')[2]
res.writeHead(200, { 'Content-Type': 'application/json' })
res.end(
JSON.stringify({
id: parseInt(userId),
name: 'John Doe',
email: 'john@example.com',
}),
)
}
// Gestion de la route /users avec POST
else if (url === '/users' && method === 'POST') {
// Récupération du body de la requête
let payload = ''
req.on('data', (body) => {
payload += body.toString()
})
req.on('end', () => {
const userData = JSON.parse(payload)
res.writeHead(201, { 'Content-Type': 'application/json' })
res.end(
JSON.stringify({
message: 'Utilisateur créé',
id: 3,
name: userData.name,
email: userData.email,
}),
)
})
}
// Gestion de la route racine
else if (url === '/' && method === 'GET') {
res.writeHead(200, { 'Content-Type': 'text/plain' })
res.end('Bienvenue sur le serveur HTTP\n')
}
// Route non trouvée
else {
res.writeHead(404, { 'Content-Type': 'text/plain' })
res.end('Route non trouvée\n')
}
})
// Démarrage du serveur sur le port 3000
server.listen(3000, () => {
console.log("Serveur en cours d'écoute sur le port 3000...")
})
Note: Une fonction callback est une fonction qui est passée en argument à une autre fonction et qui est ensuite exécutée à un moment donné, généralement après que cette fonction ait terminé son traitement. En d'autres termes, c'est une fonction qui "attend" d'être appelée une fois qu'une tâche asynchrone (comme une requête HTTP ou une opération de lecture de fichier) est terminée.