Что такое HATEOAS и какую роль этот принцип играет в REST API?

Ответ

HATEOAS (Hypermedia as the Engine of Application State) — это ограничение архитектурного стиля REST, согласно которому клиент взаимодействует с сервером полностью через гипермедиа, динамически предоставляемые в ответах сервера.

Проще говоря, вместо того чтобы клиент "зашивал" в свой код URL-адреса для действий (/users/123/deactivate), сервер в ответе сам предоставляет ссылки на возможные следующие действия.

Цель HATEOAS — уменьшить связанность (coupling) между клиентом и сервером. Клиенту не нужно знать структуру URL API, он просто следует ссылкам, которые ему предлагает сервер. Это позволяет серверу изменять свою URL-схему без необходимости обновлять клиентов.

Пример ответа API с HATEOAS:

Запрос на получение информации о заказе: GET /orders/123

Ответ сервера:

{
  "id": 123,
  "status": "shipped",
  "total": 99.99,
  "_links": {
    "self": {
      "href": "/orders/123"
    },
    "customer": {
      "href": "/customers/45"
    },
    "invoice": {
      "href": "/orders/123/invoice"
    },
    "track": {
      "href": "/shipping/track?order=123"
    }
  }
}

Клиент, получив этот ответ, знает, что он может получить счёт (invoice) или отследить (track) заказ, перейдя по соответствующим href.

Преимущества:

  • Слабая связанность: API можно развивать, не ломая старые клиенты.
  • Самодокументируемость: API становится более интуитивно понятным, так как возможные действия видны прямо в ответе.

Недостатки:

  • Усложнение: требует более продуманной реализации как на сервере, так и на клиенте.
  • Избыточность: может увеличивать размер ответа.

Ответ 18+ 🔞

Давай я тебе объясню, что это за HATEOAS такой, а то звучит как болезнь какая-то, ёпта. Представь себе, ты заходишь в бар.

Без HATEOAS это выглядит так: ты, мудак, уже заранее знаешь всю карту заведения наизусть. Ты орешь: «Эй, бармен! Налей мне пива в тот самый краник слева, который я вчера лизал! А потом дай мне меню из второго ящика, а потом позови ту официантку Тамару, которая дежурит по средам!». И если бармен вдруг переставит краники или Тамара уволится — ты, блядь, в полном ауте, стоишь и тупишь, как мартышлюшка.

А с HATEOAS — всё по-другому, хитрая жопа. Ты просто заходишь и говоришь: «Эй, бар!». А бар тебе в ответ: «О, чувак, привет! Вот тебе стул, садись. Вот меню. Хочешь пива — вот кран, нажми сюда. Хочешь закусить — вот ссылка на кухню. А ещё у нас сегодня Тамара, вот её номер, позвони». И ты, сука, просто идешь по этим подсказкам. Бармен может завтра всё переделать, но он в ответе просто даст тебе новые ссылки — и ты, ни хуя себе, снова в теме. Вот и вся магия.

Цель — чтобы твой клиентский код не был привязан к конкретным путям на сервере, как собака на цепи. Он просто как дурак идёт туда, куда ему говорят.

Пример, чтобы вообще мозг вскипел:

Ты спрашиваешь про заказ номер 123. GET /orders/123

А сервер тебе такой отвечает:

{
  "id": 123,
  "status": "В пути, жди, недоделанный",
  "total": 99.99,
  "_links": {
    "self": { "href": "/orders/123" },
    "customer": { "href": "/customers/45" },
    "invoice": { "href": "/orders/123/invoice" },
    "track": { "href": "/shipping/track?order=123" }
  }
}

Смотри, какая красота! Тебе не надо гадать, как получить счёт или где отследить посылку. Всё, блядь, лежит прямо тут. Видишь ссылку invoice? Жми на неё и получишь счёт в ебучку. Видишь track? Жми — и увидишь, где твой заказ болтается. Сервер сам тебя ведёт за ручку, как дебильчика.

Что хорошего?

  • Слабая связанность, овердохуища! Сервер может менять свои адреса как хочет, а клиенты будут просто следовать новым ссылкам. Ничего ломать не надо.
  • Самодокументируемость. Глядя на ответ, сразу понятно, что можно делать дальше. Не надо лезть в документацию, которая устарела ещё в прошлом году.

Что плохого?

  • Усложнение, ёперный театр. Надо это всё генерить на сервере, а на клиенте — разбирать. Не каждый захочет такую дичь городить.
  • Избыточность. Ответы становятся больше, потому что там эти ссылки болтаются. Хотя, если честно, в наше время гигабайтов — да похуй.

Вот и вся философия. Либо ты — умный и делаешь динамическое API, где клиент просто плывёт по течению ссылок, либо ты — конченый динозавр и зашиваешь пути в коде, а потом орешь, когда всё ломается. Выбор за тобой, чувак.