IFT3225

Cette page permet de vérifier ses acquis avant l’intra. Sur le plan du contenu, les deux pages les plus déterminantes sont Concevoir une API et Choisir une stratégie de persistance.

1. HTTP : sémantique et limites

Vérification« HTTP est sans état » : que signifie cette propriété, et quelle conséquence pratique en découle ?

Le serveur ne conserve aucun souvenir d’une requête à l’autre ; chaque requête doit porter le contexte nécessaire (identifiants, jeton). Il en résulte que n’importe quel serveur peut traiter n’importe quelle requête, ce qui facilite la mise à l’échelle ; en contrepartie, un mécanisme explicite (cookie, jeton) est requis pour reconnaître un utilisateur d’un appel à l’autre.

VérificationPOST /boites crée une boîte avec succès : quel statut retourner ? Et si le JSON est invalide ?

Création réussie → 201 Created (accompagné de la ressource créée ou d’un en-tête Location). JSON invalide ou champ manquant → 400 Bad Request. Le statut 200 est à proscrire dans les deux cas : il ne distingue pas une création d’une simple lecture et masque l’erreur.

VérificationPour ne modifier que le quartier d'une boîte, emploie-t-on PUT ou PATCH ? Et pour remplacer l'intégralité de sa représentation ?

PATCH /boites/12 convient à une modification partielle : seul le champ quartier est transmis, le reste est conservé. PUT /boites/12 correspond à un remplacement intégral : tous les champs doivent être fournis, faute de quoi un champ omis serait perdu. Le choix dépend donc de l’intention : retoucher un attribut ou réécrire la ressource.

VérificationGET /boites/9999 vise une boîte inexistante. Quel statut convient, et quelle réponse faut-il éviter ?

404 Not Found. La réponse à éviter est 200 OK accompagné d’un corps vide : elle simule un succès, induit le client en erreur et peut altérer les caches. Le statut doit refléter la réalité : la ressource n’existe pas.

2. Augmenter HTTP

VérificationSur un protocole sans état, comment reconnaître qu'un utilisateur est connecté d'une requête à l'autre ?

Le client renvoie un cookie ou un jeton à chaque requête ; le serveur l’examine pour identifier l’utilisateur.

VérificationQu'est-ce qu'un JWT, et comment permet-il une authentification sans état ?

Un JWT (JSON Web Token) est un jeton signé contenant des informations (claims) : identité de l’utilisateur, droits, échéance. Le serveur l’émet lors de la connexion ; le client le renvoie ensuite à chaque requête (généralement dans l’en-tête Authorization: Bearer …). Le serveur en vérifie la signature à l’aide de sa clé : si elle est valide, il se fie au contenu, sans conserver d’état de session.

3. REST : contraintes et conséquences

VérificationPourquoi DELETE /boites/12 plutôt que GET /boites/supprimer/12 ?

DELETE /boites/12 nomme la ressource et signifie sa suppression. GET /boites/supprimer/12 place l’action dans le chemin et recourt à GET.

VérificationSoit les routes GET /getBoites, POST /boites/42/modifier et GET /boites/supprimer/42. Quelle en est la version RESTful ?

GET /boites (lister), PATCH /boites/42 ou PUT /boites/42 (modifier) et DELETE /boites/42 (supprimer). Une ressource identifiée par son URI, des verbes standards portant l’intention, et aucune action dans le chemin : « getBoites », « modifier » et « supprimer » disparaissent.

VérificationLire une boîte précise, puis filtrer les boîtes d'un quartier : paramètre de route ou de requête pour chacun ?

Boîte précise → paramètre de route : /boites/:id identifie une ressource.
Filtre par quartier → paramètre de requête : /boites?quartier=Plateau exprime un critère sur la collection.
En règle générale, la route désigne quelle ressource, la requête précise comment filtrer, trier ou paginer.

VérificationQu'est-ce qui distingue une API « qui parle HTTP » d'une API véritablement RESTful ?

« Parler HTTP » revient à employer le transport (POST, GET) sans respecter les contraintes : action dans l’URI, verbe unique pour toute opération, absence de véritables ressources (par exemple POST /api?action=create).
Une API RESTful repose sur des ressources identifiées par URI, une interface uniforme (verbes standards, statuts appropriés, représentations), le caractère sans état et la possibilité de mise en cache (par exemple POST /boites, GET /boites/12). La distinction tient au respect des contraintes, non à l’usage de HTTP.

4. Conception d’API

VérificationPar quoi commence la conception d'une API, avant d'écrire le moindre endpoint ?

Par les questions auxquelles l’API doit répondre, puis par les ressources du domaine (les noms : station, boîte, mesure) et leurs attributs. Les endpoints en découlent : ils donnent accès à ces ressources. Partir des endpoints sans avoir nommé les ressources mène à une API d’actions hétéroclites plutôt qu’à un modèle cohérent.

VérificationL'API Lino doit lister les boîtes d'un quartier, consulter une boîte précise, et consulter les emprunts d'une boîte. Proposez les endpoints.

GET /boites?quartier=Plateau (collection filtrée), GET /boites/:id (un élément précis) et GET /boites/:id/emprunts (la relation, en chemin imbriqué). Verbes standards, filtre exprimé en paramètre de requête, relation rendue par l’imbrication du chemin.

VérificationPour exposer un historique d'emprunts potentiellement très long, comment concevoir l'endpoint afin qu'il reste utilisable ?

GET /boites/:id/emprunts avec pagination et filtres en paramètres de requête (?depuis=2026-05-01&page=2&taille=50), au lieu de renvoyer tout l’historique d’un coup. On borne la taille de la réponse et on laisse le client demander la suite, ce qui protège le serveur comme le client d’une réponse démesurée.

VérificationConcevez le flux d'échanges pour ce scénario : Alice repère une boîte de son quartier, consulte les livres qui y sont disponibles, puis en emprunte un.

Une séquence d’échanges requête-réponse, du repérage vers l’écriture :

  1. GET /boites?quartier=Rosemont répond 200 avec les boîtes du quartier.
  2. GET /boites/12/livres?disponible=true répond 200 avec les livres disponibles de la boîte choisie.
  3. POST /boites/12/emprunts (corps : { "livre_id": 87 }) répond 201 Created avec l’emprunt enregistré. Chaque étape est un échange complet et autosuffisant : HTTP étant sans état, la requête d’emprunt porte elle-même les identifiants nécessaires, sans dépendre d’un état conservé entre les appels. Le flux progresse des lectures (GET) vers la création (POST), et chaque réponse fournit au client de quoi décider de l’étape suivante.

5. Stratégies de persistance

VérificationUn serveur conserve ses boîtes dans un tableau en mémoire ; après un redémarrage, tout a disparu. Que faut-il changer, et quelle en est la conséquence sur le code ?

Il convient d’adopter une base de données pour la durabilité (et le partage entre serveurs). La mémoire reste appropriée pour un état temporaire ou non critique.

VérificationLa préférence de thème d'un utilisateur, et l'inventaire des boîtes interrogeable par quartier : sur quelle cible conserver chacun ?

Préférence de thème → côté client (cookie ou stockage du navigateur) : donnée propre à l’utilisateur, non critique, qui n’a pas à transiter par le serveur. Inventaire des boîtes → base de données : donnée durable, partagée et interrogeable (filtrer par quartier, trier, paginer). Le critère décisif est l’usage : préférence locale et jetable d’un côté, donnée de référence interrogeable de l’autre.

VérificationImbrication ou référence : quel est le compromis, en une phrase ?

L’imbrication permet une lecture en un seul accès, mais entraîne duplication possible et croissance du document. La référence évite la duplication et préserve l’indépendance des entités, mais la lecture des données liées exige une jointure. Le choix dépend du mode de lecture : données lues ensemble → imbrication ; données lues séparément ou de volume illimité → référence.

6. Express.js : mécanique d’une API

VérificationLa route app.get('/stations/:id') reçoit /stations/12?detail=complet. Comment lire 12 puis complet ?

req.params.id vaut "12" (segment de route) et req.query.detail vaut "complet" (paramètre situé après le ?). La route capture l’identité de la ressource ; la requête en précise les options.

VérificationUn gestionnaire POST observe req.body indéfini alors que le client transmet du JSON. Quelle est la cause probable, et le correctif ?

Sans app.use(express.json()), Express n’analyse pas le corps JSON, d’où un req.body indéfini. Il convient également de vérifier que le client envoie l’en-tête Content-Type: application/json.

VérificationÉcrire la route qui renvoie une boîte par son identifiant, avec un 404 lorsqu'elle est absente.
app.get("/boites/:id", async (req, res) => {
  const boite = await Boite.findById(req.params.id);
  if (!boite) {
    return res.status(404).json({ erreur: "Boîte introuvable" });
  }
  res.json(boite);
});

La lecture en base de données est asynchrone (await) ; en l’absence de résultat, le gestionnaire répond explicitement 404 plutôt que de renvoyer null avec un statut 200.

VérificationPour une création réussie, puis pour une ressource absente, quels statuts retourner ?

Création réussie → res.status(201).json(cree). Ressource absente → res.status(404).json({ erreur: "..." }). Express ne déduit pas le statut (il applique 200 par défaut) : il revient au gestionnaire de fixer le code approprié au résultat.