2016-09-12 18 views
1

Я пытаюсь обернуть голову вокруг того, как (и если) реализовать HATEOAS в моем api. Мне нравится одна из концепций кормления клиентов только действиями, которые подходят в текущей ситуации. Однако я не уверен, правильно ли реализую эту идею.HATEOAS и ссылки/действия

Скажем, у меня есть тип ресурса заказа со статусом, который может быть изменен, он может иметь различные статусы (обработка, принял, отказался, истек, успешно). Должен ли я создать следующий объект json:

{ 
    ... 
    "links": { 
     "accept": "http://example.com/order/1/accept", 
     "decline": "http://example.com/order/1/decline" 
    } 
} 

Или я создаю ненужные действия здесь? И если выше правильно, должен ли статус быть изменен с помощью PATCH или GET? И если бы это был PATCH, как бы вы знали (побеждая цель гипермедиа)?

Edit: Забыл добавить идентификатор заказа

ответ

4

Скажем, у меня есть заказ тип ресурса с состоянием, которое может быть изменено, оно может иметь различные статусы (обработка, принято, отклонено, истекли, успешное).

Предупреждение: если ваш домен не является документооборотом, вы можете оказаться в клубок, если попытаетесь сопоставить свои ресурсы с концепциями вашего домена. Jim Webber warned about this years ago; в большинстве случаев ваши ресурсы являются частью домена интеграции. Это небольшие цифровые листы бумаги, которые используются для взаимодействия с вашей моделью домена.

{ 
    ... 
    "links": { 
     "accept": "http://example.com/order/accept", 
     "decline": "http://example.com/order/decline" 
    } 
} 

Основная идея здесь в порядке - если клиент хочет вызвать протокол принятия, они знают, какую ссылку использовать; аналогично для протокола снижения. Что-нибудь еще, клиент знает, что его не следует пытаться делать, потому что ссылки недоступны; например, если цель клиента заключалась в том, чтобы истечь заказ, он знал бы, что он зашел в тупик.

Написание URI здесь немного странно; клиенту не нужно заботиться о правописании, но запрос должен быть без гражданства. Если заказ составляет типа ресурса, то как вы сообщаете, какой заказ принимать/отклонять.

А если указано выше, следует ли изменить статус с помощью PATCH или GET?

Ни то, ни другое.

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

PATCH имеет две проблемы. Во-первых, он предназначен для манипулирования документами; если ваше приложение является базой данных документа, то PATCH является фантастическим для внесения одного или нескольких изменений в область охвата.Но это не так хорошо для работы с прокси-представлениями бизнес-модели; вместо того, чтобы клиент сообщал свое намерение серверу, клиент передает побочный эффект, который его намерение будет иметь на представление, а затем сервер пытается вывести намерение из побочного эффекта.

Но вы могли бы обойти это; в конце концов, вы можете выбрать типы носителей вашей поддержки и потенциально ограничить себя теми типами, которые позволяют вам выразить намерение клиента.

Вторая проблема заключается в том, что PATCH не является идемпотентным; он имеет те же режимы отказа, что и POST - если запрос не подтвержден сервером, клиент не может легко определить, можно ли повторить запрос повторно.

Прямой вперед подход думать о правок в аналогичных положить рукописные заметки в чужой почтовый ящик

Заказ 54321 должен быть принят. Пожалуйста, сделайте это. Подписал, клиент.

Другими словами, мы не пытаемся напрямую манипулировать ресурсом заказа, а вместо этого отправляем заметку в папку «Входящие», которая будет иметь побочный эффект при манипулировании заказом. Клиент описывает желаемое изменение, сервер делает изменение (или нет, если вы разрешаете серверу иметь автономию).

Для этого подхода подходят PUT (который является идемпотентным) или POST (который не является). По сути, вы добавляете новое сообщение в коллекцию входящих сообщений и можете использовать эту идиому для выбора подходящего метода.

И если бы это было ПУТЬ, как бы узнать (победить цель гипермедиа)?

Как клиент узнает о ссылках в свойстве «ссылки»?

Как браузер знает, что делать со ссылками в документе HTML?

Ответ REST: они знают, потому что вы вложили кучу усилий в проектирование самого типа мультимедиа. В случае с сетью было потрачено много времени и усилий на разработку типа медиатекста text/html, и поэтому любой клиент, созданный с учетом HTML, может потреблять представление, созданное сервером, который разделяет это понимание - клиент и сервер отделены друг от друга, но разделяют общую точку.

В случае HTML формат мультимедиа определяет методы HTTP, связанные со ссылками (исключение является формой, позволяющей представлению указать метод из ограниченного набора). Встаньте на плечи гигантов.

+0

Спасибо за ваш тщательный ответ (я забыл добавить идентификатор ресурса, который вы правы). Поэтому, прочитав выше, вы выбрали PATCH. Какова будет полезная нагрузка json PATCH? Что-то вроде: PATCH: http://example.com/order/1/accept {status: "accept"}? – adnan

+0

Нет, я бы поставил новый ресурс. Если вы должны PATCH, тогда вы должны выбрать тип носителя PATCH. Возможно: https://tools.ietf.org/html/rfc6902 – VoiceOfUnreason

+0

Ах, ладно, извините, что вы неправильно поняли. Итак, PUT: example.com/order/1/accept с полезной нагрузкой {status: "accept"}. Или вы порекомендовали бы другую полезную нагрузку? – adnan

 Смежные вопросы

  • Нет связанных вопросов^_^