API Versioning стратегии: URL, Header, Query Parameter

← Вернуться к статьям

Введение

Версионирование API — это критически важный аспект разработки, который позволяет вносить изменения в API без поломки существующих клиентов. Правильная стратегия версионирования обеспечивает обратную совместимость и упрощает эволюцию API.

В этом руководстве мы разберем три основных подхода к версионированию API: URL versioning, Header versioning и Query parameter versioning. Узнаем их преимущества и недостатки, и когда какой подход использовать.

✅ Что вы узнаете:

📋 Содержание

Зачем нужно версионирование API? 🤔

API эволюционируют со временем: добавляются новые функции, изменяются существующие, удаляются устаревшие. Без версионирования любые изменения могут сломать существующих клиентов.

✅ Преимущества версионирования:

⚠️ Когда нужна новая версия:

URL Versioning 🔗

URL Versioning — это самый популярный подход, при котором версия API указывается в URL пути, например /api/v1/users или /api/v2/users.

Примеры URL Versioning:

Преимущества URL Versioning

✅ Плюсы:

Недостатки URL Versioning

❌ Минусы:

Реализация URL Versioning

Node.js (Express)

// routes/v1/users.js
const express = require('express');
const router = express.Router();

router.get('/users', (req, res) => {
  res.json({
    version: 'v1',
    users: [
      { id: 1, name: 'John', email: 'john@example.com' }
    ]
  });
});

module.exports = router;

// routes/v2/users.js
const express = require('express');
const router = express.Router();

router.get('/users', (req, res) => {
  res.json({
    version: 'v2',
    users: [
      { 
        id: 1, 
        name: 'John', 
        email: 'john@example.com',
        createdAt: '2025-01-01' // Новое поле в v2
      }
    ]
  });
});

module.exports = router;

// app.js
const express = require('express');
const v1Routes = require('./routes/v1/users');
const v2Routes = require('./routes/v2/users');

const app = express();

app.use('/api/v1', v1Routes);
app.use('/api/v2', v2Routes);

app.listen(3000);

Python (Flask)

# routes/v1/users.py
from flask import Blueprint, jsonify

v1_bp = Blueprint('v1', __name__, url_prefix='/api/v1')

@v1_bp.route('/users', methods=['GET'])
def get_users_v1():
    return jsonify({
        'version': 'v1',
        'users': [
            {'id': 1, 'name': 'John', 'email': 'john@example.com'}
        ]
    })

# routes/v2/users.py
from flask import Blueprint, jsonify

v2_bp = Blueprint('v2', __name__, url_prefix='/api/v2')

@v2_bp.route('/users', methods=['GET'])
def get_users_v2():
    return jsonify({
        'version': 'v2',
        'users': [
            {
                'id': 1,
                'name': 'John',
                'email': 'john@example.com',
                'createdAt': '2025-01-01'  # Новое поле в v2
            }
        ]
    })

# app.py
from flask import Flask
from routes.v1.users import v1_bp
from routes.v2.users import v2_bp

app = Flask(__name__)
app.register_blueprint(v1_bp)
app.register_blueprint(v2_bp)

if __name__ == '__main__':
    app.run(port=5000)

Header Versioning 📋

Header Versioning — это подход, при котором версия API указывается в HTTP заголовке, обычно в заголовке Accept, например Accept: application/vnd.api+json;version=1.

Примеры Header Versioning:

Преимущества Header Versioning

✅ Плюсы:

Недостатки Header Versioning

❌ Минусы:

Реализация Header Versioning

// middleware/versionMiddleware.js
function versionMiddleware(req, res, next) {
  const acceptHeader = req.headers.accept || '';
  const apiVersionHeader = req.headers['api-version'];
  
  // Парсим версию из Accept header
  const acceptMatch = acceptHeader.match(/version=(\d+)/);
  const version = apiVersionHeader || (acceptMatch ? acceptMatch[1] : '1');
  
  req.apiVersion = version;
  next();
}

// routes/users.js
const express = require('express');
const router = express.Router();

router.get('/users', versionMiddleware, (req, res) => {
  const version = req.apiVersion;
  
  if (version === '2') {
    return res.json({
      version: 'v2',
      users: [
        {
          id: 1,
          name: 'John',
          email: 'john@example.com',
          createdAt: '2025-01-01'
        }
      ]
    });
  }
  
  // По умолчанию v1
  res.json({
    version: 'v1',
    users: [
      { id: 1, name: 'John', email: 'john@example.com' }
    ]
  });
});

module.exports = router;

Query Parameter Versioning ❓

Query Parameter Versioning — это подход, при котором версия API указывается в query параметре, например /api/users?version=1 или /api/users?v=2.

Примеры Query Parameter Versioning:

Преимущества Query Parameter Versioning

✅ Плюсы:

Недостатки Query Parameter Versioning

❌ Минусы:

Реализация Query Parameter Versioning

// routes/users.js
const express = require('express');
const router = express.Router();

router.get('/users', (req, res) => {
  const version = req.query.version || req.query.v || '1';
  
  if (version === '2') {
    return res.json({
      version: 'v2',
      users: [
        {
          id: 1,
          name: 'John',
          email: 'john@example.com',
          createdAt: '2025-01-01'
        }
      ]
    });
  }
  
  // По умолчанию v1
  res.json({
    version: 'v1',
    users: [
      { id: 1, name: 'John', email: 'john@example.com' }
    ]
  });
});

module.exports = router;

Сравнение подходов 📊

Критерий URL Versioning Header Versioning Query Parameter
Простота ✅ Очень простая ⚠️ Средняя ✅ Простая
Прозрачность ✅ Версия в URL ❌ Версия в заголовке ⚠️ Версия в параметре
RESTful ❌ Не полностью ✅ Да ❌ Нет
Кэширование ✅ Легко ⚠️ Сложнее ⚠️ Сложнее
Отладка ✅ Легко ⚠️ Нужны инструменты ✅ Легко
Браузеры ✅ Легко тестировать ⚠️ Нужны инструменты ✅ Легко тестировать
Популярность ✅ Очень популярна ⚠️ Средняя ❌ Низкая

Best Practices 📚

✅ Рекомендации по версионированию:

Семантическое версионирование

📌 Формат: MAJOR.MINOR.PATCH

Deprecation Policy

// Пример ответа с предупреждением о deprecation
{
  "data": { ... },
  "deprecation": {
    "version": "v1",
    "sunset_date": "2026-06-01",
    "link": "https://api.example.com/docs/migration-v1-to-v2"
  },
  "warning": "API v1 будет удален 1 июня 2026. Пожалуйста, мигрируйте на v2."
}

Обратная совместимость 🔄

Обратная совместимость означает, что старые версии API продолжают работать после выпуска новых версий. Это критически важно для API.

✅ Правила обратной совместимости:

Стратегия миграции

План миграции на новую версию:

  1. Выпуск новой версии — параллельно со старой
  2. Уведомление о deprecation — за 6-12 месяцев
  3. Предоставление документации — гайд по миграции
  4. Поддержка обеих версий — минимум 6 месяцев
  5. Удаление старой версии — после миграции всех клиентов

Заключение

Выбор стратегии версионирования API зависит от требований проекта. URL versioning — самый популярный и простой подход, который подходит для большинства случаев. Header versioning — для RESTful API, где важна чистота URL. Query parameter versioning — простой, но менее рекомендуемый подход.

💡 Ключевые выводы:

Создайте Mock API с версионированием за 2 минуты

Хотите протестировать версионирование API? Создайте Mock API с помощью LightBox API и попробуйте различные стратегии версионирования без необходимости настраивать сложный backend.

Попробовать бесплатно →
← Вернуться к статьям