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.