2015-05-21 4 views
2

Я работаю над API веб-сервисов, используя представление REST HATEOAS.Предложить действие для потребителя в HATEOAS

Мой клиент может создать элемент (например, заглушки из BlogPost):

POST /item 
204 Created 
Content-Type: application/vnd.foo.item+json 
{ 
    "id": 42, 
    "title": "Lorem Ipsum", 
    "status": "STUB", 
    "body": "Very long text." 
    "_links": { 
    "self": { 
     "href": "/item/42" 
    }, 
    "activate": { 
     "href": "/item/42/activate" 
     }, 
    } 
} 

После этого клиент может активировать пункт следующего за activate линии связи (например, идти жить с почтой) , Поэтому он обращается к API еще раз:

POST /item/42/activate 
200 Ok 
Content-Type: application/vnd.foo.item+json 
{ 
    "id": 42, 
    "title": "Lorem Ipsum", 
    "status": "ACTIVE", 
    "body": "Very long text." 
    "_links": { 
    "self": { 
     "href": "/item/42" 
    }, 
    "permalink": { 
     "href": "/item/42/permalink" 
    } 
    } 
} 

До сих пор это нормально. Но проблема в том, что я ищу способ рассказать клиенту предложение о следующем действии (это бэкэнд-бизнес-логика).

В моем случае может быть:

  • Принесите пользователь размещать страницу после Permalink
  • Принеси пользователь магазина корзину купить почтовую дополнительные возможности (видимость, больше изображений, стартовую позицию и т.д. на ...)
  • Сообщите пользователь, что сообщение отложенного содержания обзору

Я не имею представления о том, как я мог инкапсулировать эту информацию в HATEOAS. я думал что-то вроде:

POST /item/42/activate 
200 Ok 
Content-Type: application/json 
{ 
    "suggested-action": "check-censure-panel", 
    "censure-reason": "censored (gambling)", 
    "_embedded": { 
     "foo.item": { 
     "id": 42, 
     "title": "Lorem Ipsum", 
     "status": "ACTIVE", 
     "body": "Very long text." 
     "_links": { 
     "self": { 
      "href": "/item/42" 
     }, 
     "permalink": { 
      "href": "/item/42/permalink" 
     } 
     } 
    } 
} 

Но проблема заключается в том, что каждое предложенное действие неоднородна дополнительных атрибутов, другой пример может быть:

"suggested-action": "go-to-checkout", 
    "product-order": 424242100, 

Они не имеют общий интерфейс, поэтому я не могу сделать aa vnd.foo.suggestedAction+json.

Каков наилучший способ разработки этого ответа?

+0

Это GET для активации не кажется очень спокойным. –

+0

Вы правы: опечатка. Это 'POST' –

ответ

1

Следующее действие - переход состояния, и вы, кажется, используете HAL, поэтому любые переходы состояния должны быть представлены как HAL.

Клиентам вашего приложения необходимо отреагировать на то, какое состояние переходит в ваше приложение. Таким образом, одна очень простая вещь, которую вы можете сделать, - отправить заголовок местоположения на следующий ресурс, который должно присутствовать в приложении. Вы могли бы даже перенаправить их туда вместо того, чтобы использовать их с обновленным ресурсом.

Вы можете указать следующее действие как ссылку ... и не обязательно ссылку HAL. Вы могли бы сделать это как заголовок ссылки (https://tools.ietf.org/html/rfc5988), но я думаю, что это было бы странно, я просто подниму его, чтобы отбросить домой то, что ваше приложение должно рассказать клиенту о ссылке.

Возможно, вам нужны пользовательские типы носителей, но вы можете использовать ссылки профиля (https://tools.ietf.org/html/rfc6906) и перемешать в профиль в свой тип vnd.foo. Вы можете придерживаться своего типа vnd.foo и просто определить, что существует необязательная ссылка ссылки на предлагаемое действие. Проблема в вашем примере вы определяете его с полями данных, но использовать ссылку:

{ 
    "id": 42, 
    "title": "Lorem Ipsum", 
    "status": "ACTIVE", 
    "body": "Very long text." 
    "_links": { 
     "self": { 
      "href": "/item/42" 
     }, 
     "permalink": { 
      "href": "/item/42/permalink" 
     }, 
     "x:suggested-action" : { 
      "href" : "/path/to/best/action" 
     } 
     } 

клиент может следовать по этой ссылке, представить пользователю с возможностью следовать по этой ссылке, или игнорировать его.В среднем случае, это хорошо, если ваше приложение предоставляет некоторый контекст для пользователя, как поле названия:

"x:suggested-action" : { 
    "href" : "http://path/to/check/censure/panel", 
    "title" : "Check Censure Panel" 
} 

Кроме того, вы можете дать подсказку, как к ресурсу, приложение может ожидать:

"x:suggested-action" : { 
    "href" : "http://path/to/check/censure/panel", 
    "title" : "Check Censure Panel", 
    "type" : "vnd.censure.panel/json" 
} 

лично я не люблю делать, что, как мне нравится мой клиент, чтобы реагировать на то, что я посылаю их, но это полезно, когда вы даете несколько предложенных действий:

"x:suggested-action" : [ 
    { 
    "href" : "http://path/to/check/censure/panel", 
    "title" : "Check Censure Panel", 
    "type" : "vnd.censure.panel/json" 
    }, 
    { 
    "href" : "http://path/to/checkout", 
    "title" : "Start Checkout", 
    "type" : "vnd.checkout/json" 
    } 
] 

теперь приложение может принять решение на основе четко определенных средств массовой информации типы, какие из предлагаемых действий он хочет делать, представлять или игнорировать.

+0

Как клиент представит эти возможности конечному пользователю? Или, если клиент является автоматическим, как клиент может решить альтернативные варианты? –

+0

«[клиентское приложение может принимать решения на основе четко определенных типов медиа», поскольку вы используете пользовательские типы мультимедиа. все, что ему нужно знать, это rel «x: предлагаемое действие и тип медиа, с которым он хочет иметь дело, но, как я уже сказал, я предпочитаю, чтобы мои клиенты реагировали на то, что я им даю. Я дал только несколько возможных возможностей, если бы захотел как клиент представляет их до своего пользовательского интерфейса, может быть, как кнопки или формы. Вы дали все, что могли, ссылку и заголовок, это может быть даже шаблонная ссылка. –

+0

Это не по теме, m все еще с нетерпением жду такого API. –