Gestion des versions
Fait partie de la section API REST du Journey Node.js de Coddy. Leçon 22 sur 25.
Modifier la structure d’une réponse perturbe tous les clients qui l’utilisent déjà. Une version dans le chemin permet aux anciens et aux nouveaux clients de coexister : /api/v1/orders aujourd’hui, /api/v2/orders lorsque la structure change. Lorsqu’un chemin est déplacé, l’ancien chemin répond par une redirection vers le nouveau :
GET /api/orders/5 → 308 Location: /api/v1/orders/5
POST /api/orders → 308 Location: /api/v1/ordersLes codes 301 et 302 permettent aux clients de répéter une requête POST sous forme de GET, ce qui supprime le corps. 308 signifie « répétez la même requête à cet endroit », méthode et corps compris. Dans un middleware monté, req.url ne contient plus le chemin de montage, tandis que req.originalUrl le conserve en entier :
// dans app.use('/api/orders', ...) pour GET /api/orders/5?full=1
req.url // '/5?full=1'
req.originalUrl // '/api/orders/5?full=1'Défi
FacileVotre API va évoluer d’une manière inattendue pour les anciens clients ; ajoutez donc un numéro de version à ses chemins. L’API actuelle devient la version 1, à l’adresse /api/v1/tasks, et les anciennes adresses y redirigent les clients.
- Dans
server.js, montez le routeur des tâches sur/api/v1/tasksau lieu de/api/tasks. - Toujours dans
server.js, ajoutez un intergiciel monté sur/api/tasksqui ne fait que rediriger. Il répond avec le statut 308 vers la même adresse sous/api/v1, en conservant le reste du chemin et la chaîne de requête. Dans un intergiciel monté,req.originalUrlcontient l’ancienne adresse complète. Par exemple :GET /api/tasks/2redirige vers/api/v1/tasks/2.POST /api/tasksredirige vers/api/v1/tasks.GET /api/tasks?done=false&sort=titleredirige vers/api/v1/tasks?done=false&sort=title.
Utilisez 308, et non 301 : après une réponse 308, le client répète une requête POST en POST, corps inclus.
- Dans
routes/tasks.js, la route POST définitLocationsur la nouvelle adresse, par exemple/api/v1/tasks/4pour la tâche 4.
Essayez : GET /api/tasks/2 renvoie 308, et l’onglet Headers affiche Location: /api/v1/tasks/2. La barre de requête affiche la redirection elle-même ; elle ne la suit pas. Envoyez POST { "title": "Order new chairs" } à /api/tasks : vous obtenez 308 avec Location: /api/v1/tasks, et aucune tâche n’est créée. Envoyez le même corps avec POST à /api/v1/tasks : 201 avec Location: /api/v1/tasks/4. GET /api/v1/tasks/2 renvoie la tâche 2.
Essayez vous-même
import express from 'express';
import { sendError } from './errors.js';
import taskRoutes from './routes/tasks.js';
const BOARD_ORIGIN = 'https://board.example.com';
const app = express();
// Permet aux pages de BOARD_ORIGIN d’appeler cette API depuis le navigateur.
app.use((req, res, next) => {
res.set('Access-Control-Allow-Origin', BOARD_ORIGIN);
if (req.method === 'OPTIONS') {
res.set('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS');
res.set('Access-Control-Allow-Headers', 'Content-Type');
return res.status(204).end();
}
next();
});
app.use(express.json());
app.use(express.static('public'));
app.use('/api/tasks', taskRoutes);
// Les erreurs provenant des routes arrivent ici. Un corps qui n’est pas du JSON valide est une
// erreur du client (400) ; toute autre erreur vient de nous (500).
app.use((err, req, res, next) => {
if (err.type === 'entity.parse.failed') {
return sendError(res, 400, 'invalid_json', 'The body is not valid JSON');
}
console.error(err);
sendError(res, 500, 'server_error', 'Something went wrong');
});
app.listen(3000, () => {
console.log('Task tracker API on port 3000');
});
Toutes les leçons de API REST
1Ressources et verbes
Ressources et URLCréer avec POST4Navigateurs, versions et configuration
Qu’est-ce qu’une origineAutoriser une autre origineCORSUne page qui appelle l’APIEntraînez-vous par vous-même : Playground Express