Gymterview
middle

Как версионировать REST API?

Версионирование позволяет развивать API без нарушения обратной совместимости для существующих клиентов.

Подход Пример Плюсы Минусы
Версия в URL GET /api/v1/users Простота, наглядность, легко кэшировать Нарушает принцип REST (URI = ресурс, не версия)
Кастомный заголовок X-API-Version: 1 URI остаётся чистым Менее очевидно, сложнее тестировать
Accept-заголовок (Media Type) Accept: application/vnd.myapi.v1+json Наиболее RESTful Сложнее в реализации и тестировании
Query-параметр GET /api/users?version=1 Простота Загрязняет URI, может конфликтовать с параметрами

На практике версия в URL — самый распространённый и рекомендуемый подход для большинства проектов благодаря своей простоте и прозрачности.

Примеры реализации в Spring
// 1. Версия в URL
@RestController
@RequestMapping("/api/v1/users")
public class UserControllerV1 {
    @GetMapping
    public List<UserV1Dto> getUsers() { ... }
}

@RestController
@RequestMapping("/api/v2/users")
public class UserControllerV2 {
    @GetMapping
    public List<UserV2Dto> getUsers() { ... }
}

// 2. Версия в заголовке
@GetMapping(value = "/users", headers = "X-API-Version=1")
public List<UserV1Dto> getUsersV1() { ... }

@GetMapping(value = "/users", headers = "X-API-Version=2")
public List<UserV2Dto> getUsersV2() { ... }

// 3. Версия через Accept-заголовок
@GetMapping(value = "/users", produces = "application/vnd.myapi.v1+json")
public List<UserV1Dto> getUsersV1() { ... }

@GetMapping(value = "/users", produces = "application/vnd.myapi.v2+json")
public List<UserV2Dto> getUsersV2() { ... }

На собеседовании: нужно знать все четыре подхода с их плюсами и минусами. Частая ошибка — не упомянуть, что версия в URL — самый популярный на практике, хотя формально не самый RESTful.