Menu
CoddyTech

Pengelolaan Versi

Termasuk bagian REST API dalam perjalanan Node.js di Coddy. Pelajaran 22 dari 25.

Mengubah bentuk respons merusak semua client yang sudah menggunakannya. Versi di jalur memungkinkan client lama dan baru berjalan berdampingan: /api/v1/orders sekarang, /api/v2/orders saat bentuknya berubah. Saat jalur berpindah, jalur lama merespons dengan pengalihan ke jalur baru:

GET  /api/orders/5   →  308  Location: /api/v1/orders/5
POST /api/orders     →  308  Location: /api/v1/orders

301 dan 302 memungkinkan client mengulangi POST sebagai GET, sehingga isi permintaan hilang. 308 menyatakan "ulangi permintaan yang sama di sana", termasuk method dan isi permintaan. Di dalam middleware yang dipasang, req.url sudah kehilangan jalur pemasangan, sedangkan req.originalUrl tetap menyimpan seluruh jalurnya:

// di app.use('/api/orders', ...) untuk GET /api/orders/5?full=1
req.url          // '/5?full=1'
req.originalUrl  // '/api/orders/5?full=1'
challenge icon

Tantangan

Mudah

API-mu akan berubah dengan cara yang tidak diperkirakan client lama, jadi tambahkan nomor versi pada path-nya. API saat ini menjadi versi 1, di /api/v1/tasks, dan alamat lama mengarahkan client ke sana.

  1. Di server.js, pasang router tasks di /api/v1/tasks, bukan di /api/tasks.
  2. Juga di server.js, tambahkan middleware yang dipasang di /api/tasks dan hanya mengalihkan alamat. Middleware ini merespons dengan status 308 ke alamat yang sama di bawah /api/v1, dengan tetap mempertahankan sisa path dan string kueri. Di dalam middleware yang dipasang, req.originalUrl menyimpan alamat lama secara lengkap. Contoh:
    • GET /api/tasks/2 dialihkan ke /api/v1/tasks/2.
    • POST /api/tasks dialihkan ke /api/v1/tasks.
    • GET /api/tasks?done=false&sort=title dialihkan ke /api/v1/tasks?done=false&sort=title.

    Gunakan 308, bukan 301: setelah menerima 308, client mengulangi POST sebagai POST, termasuk body-nya.

  3. Di routes/tasks.js, rute POST menetapkan Location ke alamat baru, misalnya /api/v1/tasks/4 untuk task 4.

Coba: GET /api/tasks/2 mengembalikan 308, dan tab Headers menampilkan Location: /api/v1/tasks/2. Bilah permintaan menampilkan pengalihan itu sendiri, bukan mengikutinya. Kirim POST { "title": "Order new chairs" } ke /api/tasks: kamu akan mendapat 308 dengan Location: /api/v1/tasks, dan tidak ada task yang dibuat. Kirim POST dengan body yang sama ke /api/v1/tasks: hasilnya 201 dengan Location: /api/v1/tasks/4. GET /api/v1/tasks/2 mengembalikan task 2.

Coba sendiri

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();

// Memungkinkan halaman di BOARD_ORIGIN memanggil API ini dari browser.
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);

// Error dari route berakhir di sini. Body yang bukan JSON valid adalah
// kesalahan client (400); selebihnya kesalahan kita (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');
});

Semua pelajaran di REST API

Latihan sendiri: Playground Express