Versionierung
Teil des Abschnitts REST-APIs der Node.js-Journey von Coddy. Lektion 22 von 25.
Eine Änderung der Antwortstruktur bringt jeden Client zum Scheitern, der sie bereits verwendet. Eine Version im Pfad ermöglicht es alten und neuen Clients, parallel zu bestehen: heute /api/v1/orders, /api/v2/orders, wenn sich die Struktur ändert. Wenn ein Pfad verschoben wird, antwortet der alte Pfad mit einer Weiterleitung zum neuen:
GET /api/orders/5 → 308 Location: /api/v1/orders/5
POST /api/orders → 308 Location: /api/v1/ordersBei 301 und 302 können Clients einen POST als GET wiederholen, wodurch der Body verloren geht. 308 bedeutet: „Wiederhole dieselbe Anfrage dort“, einschließlich Methode und Body. Innerhalb einer eingebundenen Middleware hat req.url den Einbindungspfad verloren, während req.originalUrl ihn vollständig beibehält:
// in app.use('/api/orders', ...) für GET /api/orders/5?full=1
req.url // '/5?full=1'
req.originalUrl // '/api/orders/5?full=1'Aufgabe
EinfachDeine API wird sich auf eine Weise ändern, die alte Clients nicht erwarten, deshalb solltest du eine Versionsnummer in ihre Pfade aufnehmen. Die heutige API wird zu Version 1 unter /api/v1/tasks, und die alten Adressen leiten Clients dorthin weiter.
- Binde in
server.jsden Tasks-Router unter/api/v1/tasksstatt unter/api/tasksein. - Füge ebenfalls in
server.jseine Middleware hinzu, die unter/api/taskseingebunden ist und ausschließlich weiterleitet. Sie antwortet mit dem Status 308 und leitet an dieselbe Adresse unter/api/v1weiter, wobei der restliche Pfad und der Query-String erhalten bleiben. Innerhalb einer eingebundenen Middleware enthältreq.originalUrldie vollständige alte Adresse. Zum Beispiel:GET /api/tasks/2leitet weiter zu/api/v1/tasks/2.POST /api/tasksleitet weiter zu/api/v1/tasks.GET /api/tasks?done=false&sort=titleleitet weiter zu/api/v1/tasks?done=false&sort=title.
Verwende 308, nicht 301: Nach einem 308 wiederholt ein Client einen POST als POST, einschließlich des Bodys.
- In
routes/tasks.jssetzt die POST-RouteLocationauf die neue Adresse, zum Beispiel/api/v1/tasks/4für Aufgabe 4.
Probiere es aus: GET /api/tasks/2 gibt 308 zurück, und im Tab „Headers“ wird Location: /api/v1/tasks/2 angezeigt. Die Anfrageleiste zeigt die Weiterleitung selbst; sie folgt ihr nicht. Sende POST mit { "title": "Order new chairs" } an /api/tasks: Du erhältst 308 mit Location: /api/v1/tasks, und es wird keine Aufgabe erstellt. Sende denselben Body per POST an /api/v1/tasks: 201 mit Location: /api/v1/tasks/4. GET /api/v1/tasks/2 gibt Aufgabe 2 zurück.
Probier es selbst
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();
// Ermöglicht Seiten auf BOARD_ORIGIN, diese API vom Browser aus aufzurufen.
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);
// Fehler aus den Routen landen hier. Ein Body, der kein gültiges JSON enthält, ist ein
// Fehler des Clients (400); alles andere ist unser Fehler (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');
});
Alle Lektionen in REST-APIs
1Ressourcen und Verben
Ressourcen und URLsErstellen mit POST4Browser, Versionen und Konfiguration
Was ist ein Origin?Einen anderen Origin zulassenCORSEine Seite, die die API aufruftÜbe selbstständig: Express-Playground