Wersjonowanie
Część sekcji API REST ścieżki Node.js w Coddy. Lekcja 22 z 25.
Zmiana struktury odpowiedzi powoduje, że przestaje ona działać u każdego klienta, który już z niej korzysta. Wersja w ścieżce pozwala starym i nowym klientom działać równolegle: dziś /api/v1/orders, a gdy struktura się zmieni — /api/v2/orders. Gdy ścieżka ulega zmianie, stara ścieżka odpowiada przekierowaniem do nowej:
GET /api/orders/5 → 308 Location: /api/v1/orders/5
POST /api/orders → 308 Location: /api/v1/ordersKody 301 i 302 pozwalają klientom ponowić żądanie POST jako GET, co powoduje utratę treści żądania. 308 oznacza „ponów tam to samo żądanie” — z tą samą metodą i treścią. W zamontowanym middleware req.url nie zawiera już ścieżki montowania, a req.originalUrl zachowuje ją w całości:
// w app.use('/api/orders', ...) dla GET /api/orders/5?full=1
req.url // '/5?full=1'
req.originalUrl // '/api/orders/5?full=1'Wyzwanie
ŁatwyTwoje API będzie zmieniać się w sposób, którego starsi klienci się nie spodziewają, dlatego umieść numer wersji w jego ścieżkach. Dzisiejsze API staje się wersją 1 pod adresem /api/v1/tasks, a stare adresy kierują tam klientów.
- W pliku
server.jszamontuj router zadań pod adresem/api/v1/taskszamiast/api/tasks. - Również w pliku
server.jsdodaj middleware zamontowany pod adresem/api/tasks, który tylko przekierowuje. Odpowiada on statusem 308, kierując na ten sam adres pod/api/v1i zachowując pozostałą część ścieżki oraz ciąg zapytania. W zamontowanym middlewarereq.originalUrlzawiera pełny stary adres. Na przykład:GET /api/tasks/2przekierowuje do/api/v1/tasks/2.POST /api/tasksprzekierowuje do/api/v1/tasks.GET /api/tasks?done=false&sort=titleprzekierowuje do/api/v1/tasks?done=false&sort=title.
Użyj 308, a nie 301: po otrzymaniu 308 klient ponawia żądanie POST jako POST, wraz z treścią.
- W pliku
routes/tasks.jstrasa POST ustawiaLocationna nowy adres, na przykład/api/v1/tasks/4dla zadania 4.
Wypróbuj: GET /api/tasks/2 zwraca 308, a karta Nagłówki pokazuje Location: /api/v1/tasks/2. Pasek żądania pokazuje samo przekierowanie; nie podąża za nim. Wyślij żądanie POST z treścią { "title": "Order new chairs" } na adres /api/tasks: otrzymasz 308 z nagłówkiem Location: /api/v1/tasks, a żadne zadanie nie zostanie utworzone. Wyślij tę samą treść żądaniem POST na adres /api/v1/tasks: otrzymasz 201 z nagłówkiem Location: /api/v1/tasks/4. GET /api/v1/tasks/2 zwraca zadanie 2.
Spróbuj swoich sił
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();
// Umożliwia stronom z BOARD_ORIGIN wywoływanie tego API z przeglądarki.
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);
// Tutaj trafiają błędy z tras. Treść żądania, która nie jest poprawnym JSON, to
// błąd klienta (400); wszystkie pozostałe błędy są po naszej stronie (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');
});
Wszystkie lekcje w sekcji API REST
1Zasoby i czasowniki
Zasoby i URL-eTworzenie za pomocą POST4Przeglądarki, wersje i konfiguracja
Czym jest originZezwalanie na dostęp z innego originCORSStrona wywołująca APIPoćwicz samodzielnie: Edytor online Express