Що таке HATEOAS?
Без HATEOAS:
Junior Level
HATEOAS (Hypermedia As The Engine Of Application State) — це принцип REST, при якому сервер повертає не тільки дані, але й посилання на можливі дії.
Простий приклад:
Без HATEOAS:
{
"id": 101,
"status": "NEW"
}
З HATEOAS:
{
"id": 101,
"status": "NEW",
"_links": {
"self": { "href": "/orders/101" },
"payment": { "href": "/orders/101/pay" },
"cancel": { "href": "/orders/101/cancel" }
}
}
Навіщо це потрібно?
- Клієнт не повинен “знати” URLs — він просто слідує за посиланнями
- Якщо сервер змінить URLs, клієнт не зламається
- API стає самодокументованим
Аналогія:
Це як веб-сайт: ви не знаєте всі URL напам’ять, ви просто клікаєте за посиланнями на сторінці.
Middle Level
Концепція Affordances (Можливості)
У HATEOAS посилання — це не просто URL, це Affordances (можливості):
- Affordance (у контексті HATEOAS) — підказка сервера клієнту про те, які дії зараз можливі. Як кнопка на веб-сторінці «підказує», що її можна натиснути. Якщо сервер не повернув посилання
rel="delete"— значить, видалення зараз неможливе. - Якщо у користувача немає прав на видалення — сервер просто не надішле посилання
rel="delete" - Клієнту не потрібно дублювати бізнес-логіку перевірки прав
- Достатньо:
if (response.links.delete) showDeleteButton()
Стандарт HAL (Hypertext Application Language)
Найпопулярніший формат. Використовує поле _links:
{
"id": 101,
"status": "NEW",
"_links": {
"self": { "href": "/orders/101" },
"payment": { "href": "/orders/101/pay" },
"cancel": { "href": "/orders/101/cancel" }
}
}
Spring HATEOAS
Бібліотека використовує RepresentationModel і LinkDiscoverer:
WebMvcLinkBuilderбудує посилання динамічно, зчитуючи маппінги контролерів- Проблема: За проксі (Nginx/API Gateway) посилання можуть містити внутрішній IP
- Рішення: Заголовки
X-Forwarded-*і налаштуванняForwardedHeaderFilter
Продуктивність
- Payload Overhead: Для одного ресурсу оверхед 30-50%. Для колекцій із 100+ елементів — до 2-3x, оскільки кожен запис містить свої посилання.
- Оптимізація: Посилання тільки в детальне представлення (Single Resource), у списках — тільки
self - CPU Cost: Генерація посилань для 1000 елементів вимагає ресурсів (рефлексія у Spring)
Edge Cases
- Версіонування: Якщо змінили шлях до ендпоінту оплати, клієнт, що використовує HATEOAS, не помітить — він бере URL із посилання. Це забезпечує ідеальну зворотну сумісність
- Client Caching: Кешування відповідей з HATEOAS може бути небезпечним, якщо посилання залежать від прав користувача. Якщо HATEOAS-відповіді кешуються і посилання залежать від прав користувача, додайте
Vary: Authorization, інакше CDN може віддати кешовану відповідь з чужими посиланнями.
Senior Level
Коли НЕ використовувати HATEOAS
- Внутрішні мікросервіси — оверхед без користі
- Мобільні додатки з фіксованими екранами — URL не змінюються
- Highload-системи — де кожен байт на рахунку
- Клієнт і бекенд однієї команди — coupling вже мінімальний
HATEOAS як State Machine
HATEOAS реалізує патерн State Machine на рівні мережевого протоколу:
- Клієнт — “тупий” виконавець, який переходить за посиланнями
- Сервер керує станом додатку через доступні посилання
- Це радикально знижує coupling між фронтендом і бекендом
Spring HATEOAS (Under the hood)
RepresentationModel— базовий клас для ресурсів із посиланнямиLinkDiscoverer— парсить і знаходить посилання у відповідях- Проблема з проксі:
WebMvcLinkBuilderбудує посилання на основі внутрішніх маппінгів. За Nginx/API Gateway посилання містять внутрішній IP
Продуктивність і Highload
Payload Overhead
У Highload-системах HATEOAS може бути проблемою:
- Для одного ресурсу оверхед 30-50%. Для колекцій із 100+ елементів — до 2-3x
- CPU на генерацію посилань для кожного запису (рефлексія)
Оптимізації
- Посилання тільки в Single Resource, у Collections — тільки
self - Компактні формати посилань (мінімальні rel імена)
- Кешування шаблонів посилань
Діагностика і Моніторинг
- Discoverability: Можна “гуляти” по API через HAL Browser, клікаючи за посиланнями
- Broken Links: Моніторинг має перевіряти валідність генерованих посилань. Якщо
selfведе на 404 — баг генератора - Vary Header: Якщо HATEOAS-відповіді кешуються і посилання залежать від прав користувача, додайте
Vary: Authorization, інакше CDN може віддати кешовану відповідь з чужими посиланнями.
🎯 Шпаргалка для співбесіди
Обов’язково знати:
- HATEOAS = Hypermedia As The Engine Of Application State — сервер повертає дані + посилання на дії
- Клієнт не повинен знати URLs — він слідує за посиланнями з відповідей сервера
- Affordances — підказки сервера про доступні дії; немає посилання
rel="delete"= видалення неможливе - Стандарт HAL використовує поле
_linksзself,payment,cancelі т.д. - Payload Overhead: 30-50% для одного ресурсу, до 2-3x для колекцій із 100+ елементів
- HATEOAS не потрібен для: внутрішніх мікросервісів, мобільних додатків, highload-систем
- Spring HATEOAS:
RepresentationModel+WebMvcLinkBuilder; проблема з проксі вирішується черезX-Forwarded-*
Часті уточнюючі запитання:
- Що таке Affordance у контексті HATEOAS? — Підказка сервера про доступні дії (як кнопка на сторінці)
- Чому HATEOAS збільшує розмір JSON? — Кожен запис містить посилання; для колекцій оверхед до 2-3x
- Як вирішити проблему посилань за проксі? — Заголовки X-Forwarded-* і налаштування ForwardedHeaderFilter у Spring
- Коли HATEOAS точно не потрібен? — Внутрішні мікросервіси, мобільні з фіксованими екранами, highload
Червоні прапорці (НЕ говорити):
- «HATEOAS потрібен у кожному проекті» — надлишковий для внутрішніх API і мобільних
- «HATEOAS — це просто посилання в JSON» — це ще й State Machine і управління coupling
- «Посилання HATEOAS можна кешувати без Vary: Authorization» — CDN віддасть чужі посилання іншому користувачу
- «HATEOAS зменшує розмір відповіді» — збільшує на 30-50% для одного ресурсу
Пов’язані теми:
- [[Що таке REST]]
- [[Що таке RESTful API дизайн]]
- [[Чи варто використовувати дієслова в URL]]
- [[Як організувати версіонування REST API]]
- [[Що таке Accept header]]