Menu
CoddyTech

Версионирование

Часть раздела REST API путешествия по Node.js на Coddy. Урок 15 из 18.

Изменение структуры ответа нарушает работу всех клиентов, которые уже его используют. Версия в пути позволяет старым и новым клиентам работать параллельно: сегодня /api/v1/orders, а при изменении структуры — /api/v2/orders. Для изменившихся путей отправляется перенаправление:

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

При ответах 301 и 302 клиенты могут повторить запрос POST как GET, из-за чего тело запроса теряется. 308 означает «повторить там тот же запрос», включая метод и тело. В подключённом промежуточном обработчике req.url уже не содержит путь монтирования, а req.originalUrl сохраняет его целиком:

// в app.use('/api/orders', ...) для GET /api/orders/5?full=1
req.url          // '/5?full=1'
req.originalUrl  // '/api/orders/5?full=1'
challenge icon

Задание

Легко
  • Подключи маршрутизатор задач по адресу /api/v1/tasks.
  • Каждый старый путь /api/tasks отвечает перенаправлением 308 на тот же путь в /api/v1, включая строку запроса.
  • Новые задачи получают Location: /api/v1/tasks/<id>.

Отправь GET /api/tasks/2, POST /api/tasks с { "title": "Order new chairs" }, затем GET /api/v1/tasks/2.

Попробуйте сами

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();
app.use(express.json());

// Позволяет страницам на BOARD_ORIGIN обращаться к этому API из браузера.
app.use((req, res, next) => {
    res.set('Access-Control-Allow-Origin', BOARD_ORIGIN);
    res.set('Access-Control-Allow-Credentials', 'true');
    if (req.method === 'OPTIONS') {
        res.set('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE');
        res.set('Access-Control-Allow-Headers', 'Content-Type');
        return res.status(204).end();
    }
    next();
});

app.use(express.static('public'));

app.use('/api/tasks', taskRoutes);

// Ошибки из маршрутов обрабатываются здесь. Тело запроса, не являющееся допустимым JSON, — это
// ошибка клиента (400); всё остальное — наша ошибка (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');
});

Все уроки раздела REST API