Router sans framework
Méthode + segments d’URL, ressources et 404.
Objectifs
À la fin de cette leçon, vous saurez :
- construire un routage par méthode + URL ;
- extraire un identifiant de chemin (
/tasks/7) ; - répondre avec les bons codes de statut.
🔗 Pour vous rafraîchir la mémoire : anatomie d'une requête HTTP · méthodes HTTP et codes de statut · en-têtes HTTP et JSON
Le routeur minimal
Un routeur, c'est un if bien organisé :
import { createServer } from "node:http";
const taches = [
{ id: 1, titre: "Apprendre HTTP" },
{ id: 2, titre: "Écrire un serveur" },
];
const serveur = createServer(function (requete, reponse) {
const url = new URL(requete.url, "http://localhost");
const chemin = url.pathname; // "/tasks/7"
const segments = chemin.split("/").filter(Boolean); // ["tasks", "7"]
if (requete.method === "GET" && chemin === "/tasks") {
return repondreJSON(reponse, 200, taches);
}
if (requete.method === "POST" && chemin === "/tasks") {
return repondreJSON(reponse, 201, { message: "création à venir" });
}
if (requete.method === "GET" && segments[0] === "tasks" && segments[1]) {
const tache = taches.find((t) => t.id === Number(segments[1]));
if (!tache) {
return repondreJSON(reponse, 404, { erreur: "Tâche inconnue" });
}
return repondreJSON(reponse, 200, tache);
}
repondreJSON(reponse, 404, { erreur: "Route inconnue" });
});
function repondreJSON(reponse, statut, donnees) {
reponse.writeHead(statut, { "Content-Type": "application/json" });
reponse.end(JSON.stringify(donnees));
}
serveur.listen(3000);
Ce que ce code installe
| Pièce | Rôle | Lien avec le cours |
|---|---|---|
new URL(...) | parse l'URL proprement (chemin + query) | chapitre 11 |
segments | découpe /tasks/7 en morceaux exploitables | routing |
find sur id | lecture d'une ressource précise | REST |
| 404 final | aucune route ne correspond | codes de statut |
Testez :
curl localhost:3000/tasks
curl localhost:3000/tasks/1
curl localhost:3000/tasks/99 # → 404
curl localhost:3000/inconnu # → 404
Les query parameters aussi
// GET /tasks?page=2
const page = Number(url.searchParams.get("page") ?? "1");
searchParams lit ce qui suit le ? — déjà décodé et prêt. Vous venez de couvrir pagination et filtres sans framework.
Exercice
- Ajoutez la route
DELETE /tasks/:id: retirez du tableau, répondez 204 sans corps. - Ajoutez
GET /tasks/compte— attention : placez-la AVANT la route générique/tasks/:id, sinon "compte" sera traité comme identifiant. - Que renvoie votre serveur pour
/TASKS? Corrigez avec une normalisation en minuscules.
Résumé
- Routeur = méthode + chemin découpé en segments.
- Ressource précise = segment d'id + find + 404 si absent.
- searchParams pour la query string ; ordre des tests = piège classique.
Correction disponibleCherchez d’abord par vous-même.Voir la correction
Correction
Réponses détaillées
Question 1.
if (requete.method === "DELETE" && segments[0] === "tasks" && segments[1]) {
const index = taches.findIndex((t) => t.id === Number(segments[1]));
if (index === -1) return repondreJSON(reponse, 404, { erreur: "Inconnue" });
taches.splice(index, 1);
reponse.writeHead(204);
return reponse.end();
}
Question 3. /TASKS tombe dans le 404 final : les chemins HTTP sont sensibles à la casse par convention. Correctif : const chemin = url.pathname.toLowerCase(); dès le début du handler.