Стоит ли достигать HATEOAS для обслуживания веб-сервисов в реальном мире?
Я много читал о потенциальных преимуществах, если мне нужно было преобразовать мои существующие Restful веб-сервисы как можно более подходящие для HATEOS. Я понимаю важность предоставления ссылок в полезной нагрузке, чтобы снизить потребительскую нагрузку при запоминании следующих действительных доступных действий. Тем не менее, я не могу представить себе, как это поможет потребителю моих Restful веб-сервисов на самом деле.
Чтобы проиллюстрировать это, я беру этот пример из книги Rest In Practice о заказе кофе: -
<order xmlns="http://schemas.restbucks.com">
<location>takeAway</location>
<item>
<name>latte</name>
<quantity>1</quantity>
<milk>whole</milk>
<size>small</size>
</item>
<cost>2.0</cost>
<status>payment-expected</status>
<link rel="payment" href="#" onclick="location.href='https://restbucks.com/payment/1234'; return false;" />
</order>
В принципе, это позволяет потребителю произвести платеж, определенный тегом <link>
. Однако на самом деле потребителю по-прежнему необходимо знать всю семантику вызова этой веб-службы, например, какой метод (POST или PUT) использовать, какие параметры запроса использовать в полезной нагрузке для осуществления платежа и т.д... в другом слове, потребитель все еще должен полагаться на документацию WADL, чтобы знать, как сделать этот веб-сервис успешным. Эти теги, вероятно, имеют больше смысла, если все они используют GET на одном конкретном элементе. В противном случае, я действительно не вижу больших преимуществ при определении ссылок здесь... кроме того, что потребитель знает, какие действия они могут вызывать дальше, а затем ссылается на WADL, чтобы определить, как правильно его вызывать.
Моя следующая забота - это возможность получить очень тяжелую полезную нагрузку со всеми тегами <link>
. Например, если GET on/projects/1/users возвращает всю информацию пользователя, относящуюся к проекту 1, я предполагаю, что у меня появятся следующие теги: -
<project>
<users>
<user id="12" name="mike" ... />
<user id="23" name="kurt" ... />
<user id="65" name="corey" ... />
</user>
<links>
<link rel="self" href="#" onclick="location.href='http://server/projects/1/users'; return false;"/>
<link rel="create_user" href="#" onclick="location.href='http://server/projects/1/users'; return false;"/>
<link rel="get_user_mike" href="#" onclick="location.href='http://server/projects/1/users/12'; return false;"/>
<link rel="get_user_kurt" href="#" onclick="location.href='http://server/projects/1/users/23'; return false;"/>
<link rel="get_user_corey" href="#" onclick="location.href='http://server/projects/1/users/65'; return false;"/>
...
</links>
</project>
Если в проекте говорится, что у 500 пользователей... не было бы 500 пользовательских ссылок в полезной нагрузке? В противном случае, каков наилучший подход при перепроектировании моих веб-сервисов для решения этой ситуации? Или это приемлемо в реальном мире?
Любые мысли или предложения здесь очень ценятся. Спасибо.
Ответы
Ответ 1
Чтобы понять, почему это правильно, представьте свой API без подхода HATEOAS: вам придется публиковать каждую возможную схему URI в своей документации (или в вашем WADL, если это ваша вещь), и из этот пункт на вас не может изменить их, не разбивая ваших клиентов.
В сущности, ваши клиенты будут неразрывно связаны с вашим выбором макета URI. Это уровень связи, который можно легко избежать, просто задокументировав, где ссылки находятся в ваших медиа-типах, а не документирует, как выглядят ссылки.
Тем не менее, может быть, хорошо, что ваше приложение должно принять этот подход, и это прекрасно. Просто имейте в виду, что вы будете придерживаться своего макета URI в течение долгого времени. Однако вы будете в хорошей компании.
Ответ 2
В вашем конкретном примере, я думаю, имеет смысл вернуться к HTML. Если вы отобрадите список из 500 ресурсов в HTML, включите ли вы ссылку на каждый ресурс, чтобы пользователи могли получать дополнительную информацию? Вероятно, вы бы это сделали. API REST не сильно отличается: если вы возвращаете список из 500 ресурсов, вам нужно включить 500 ссылок, чтобы пользователи могли получать больше информации о каждом ресурсе.
Ожидание того, что клиенты будут создавать URL-адреса на основе некоторых идентификаторов или имен, будет напоминать просить пользователей вручную вводить URL-адреса в адресной строке браузера.
Вот очень хорошая статья об этом, в частности:
Подобно тому, как файлы HTML ссылаются друг на друга с помощью тегов или так же, как файлы XML связаны друг с другом с XLink, вся передача состояния должна выполняться исключительно как реакция на ссылку, найденную внутри представления
Ответ 3
Просто боковая точка в 500 пользовательских вещах: я не эксперт, но я понимаю, что вы можете спокойно разместить разбивку на страницы:
/проект/1/пользователей/страниц/1
<links>
...
<link rel="get_user_mike" href="http://server/projects/1/users/12"/>
<link rel="get_user_kurt" href="http://server/projects/1/users/23"/>
<link rel="get_user_corey" href="http://server/projects/1/users/65"/>
<link rel="get_page_2" href="http://server/projects/1/users/pages/2"/>
</links>
Ответ 4
На самом деле это не ответ, просто некоторые советы по принятию HATEOAS. Вам не нужно включать сотни ссылок, вы можете либо включить 1 ссылку на полный список 500, 1 ссылку на разбитый на страницы подмножество ссылок, либо включить разбиение подмножества в ответе и добавить ссылку следующей страницы.
В ответ на вещь WADL вы должны использовать встроенные средства независимо от вашего формата содержимого, например. В HTML, который будет LINK
и A
, чтобы указать, что клиент должен делать запросы GET и FORM
элементы для запросов POST. Очевидно, что другие форматы и API XLink и XMLHTTPRequest поддерживают HTTP лучше, чем HTML. Вы можете посмотреть http://tools.ietf.org/html/draft-nottingham-link-hint