Skip to main content

4. 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

  1. Architecture Client-Serveur

    • Séparation entre interface utilisateur (client) et stockage de données (serveur)
  2. Sans état (Stateless)

    • Chaque requête contient toutes les informations nécessaires
    • Le serveur ne garde pas de "session"
  3. Cacheable

    • Les réponses indiquent si elles peuvent être mises en cache
  4. Interface uniforme

    • URLs cohérentes et prévisibles
  5. Système en couches

    • Le client ne sait pas s'il parle directement au serveur ou à un intermédiaire
  6. 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.

Structure requête HTTP

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.

  • GET permet de récupérer des données
  • POST permet de créer une ressource
  • PATCH permet de modifier partiellement une ressource
  • PUT permet de remplacer entièrement une ressource
  • DELETE permet de supprimer une ressource
  • 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.

Sémantique des URL en REST

Dans une API REST, une URL ne décrit pas une action, mais une ressource.
La sémantique des URL est un élément fondamental : une API bien conçue doit pouvoir être comprise simplement en lisant ses routes.

Une bonne règle à retenir est la suivante :

Une URL désigne une ressource, la méthode HTTP décrit l’action.


Une URL représente une ressource

Une ressource est une entité manipulée par l’API : utilisateur, article, commande, etc.

/users
/users/42
/orders/12
  • /users représente la collection des utilisateurs
  • /users/42 représente un utilisateur spécifique
  • /orders/12 représente une commande précise

Les ressources sont généralement nommées au pluriel et de manière explicite.


Les actions sont portées par les méthodes HTTP

Il est important de ne pas mettre de verbes dans les URL.

Mauvaises pratiques

GET /getUsers
POST /createUser
POST /deleteUser/42

Bonnes pratiques

GET    /users
POST /users
GET /users/42
DELETE /users/42

Hiérarchie et relations entre ressources

Les URL peuvent refléter des relations entre ressources.

/users/42/posts
/users/42/posts/3
  • /users/42/posts : tous les articles de l’utilisateur 42
  • /users/42/posts/3 : un article précis de l’utilisateur 42

Cette hiérarchie permet de rendre l’API plus lisible et plus intuitive.


Paramètres de chemin et paramètres de requête

Il est important de distinguer les paramètres de chemin et les paramètres de requête.

Paramètres de chemin (path parameters)

Ils identifient une ressource précise.

/users/42

Paramètres de requête (query parameters)

Ils servent à filtrer, trier ou paginer une collection.

/users?role=admin&page=2&limit=10
  • Les paramètres de chemin identifient une ressource
  • Les paramètres de requête modifient la manière de récupérer une collection

Cas particuliers : actions métier

Certaines actions métier ne correspondent pas directement à une opération CRUD classique (par exemple : activer un compte, valider une commande, réinitialiser un mot de passe).

Deux approches sont possibles :

1. Créer une sous-ressource métier

POST /users/42/activation

2. Modifier l’état de la ressource existante

PATCH /users/42
{
"status": "active"
}

Ces deux approches sont acceptables tant que la sémantique reste cohérente et explicite.


Exemple de routes REST cohérentes

GET    /articles
GET /articles/10
POST /articles
PATCH /articles/10
DELETE /articles/10

Ces routes permettent de comprendre immédiatement :

  • quelles ressources sont manipulées
  • quelles actions sont possibles
  • comment l’API est structurée

À retenir

  • Une URL représente une ressource, pas une action
  • Les verbes doivent être portés par la méthode HTTP
  • Les ressources sont nommées de manière claire et cohérente
  • Une API REST bien conçue est lisible sans documentation

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).

CodeSignificationDescription
200OKLa 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.
201CreatedLa 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.
204No ContentLa 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.
400Bad RequestLa 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.
401UnauthorizedLa requête nécessite une authentification. Ce code est souvent renvoyé lorsqu'une API requiert une clé d'API ou un jeton d'authentification.
403ForbiddenLe serveur comprend la requête, mais il refuse de l'exécuter. Cela peut être dû à des permissions insuffisantes.
404Not FoundLa 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.
405Method Not AllowedLa méthode HTTP utilisée (par exemple, GET, POST, PUT, DELETE) n'est pas autorisée pour la ressource spécifiée.
500Internal Server ErrorIl 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.