优选地,用户代理应该只知道根URI,以便能够探索服务的所有功能 – 也就是说,我希望它在 maturity model中的第3级.
现在,用户代理应该能够创建一些资源,并在以后编辑它们.在创建/编辑时,用户代理需要访问其他一些资源/枚举.
foo资源:
{ "category" : "category chosen from an enumeration of possible categories","color" : "color chosen from an enumeration of possible colors","aRelatedResource" : "resource identifier from chosen from a collection" }
鉴于前面提到的要求,我提出了以下模式:
有一个fooRoot资源:
{ // no properties,only links "_links" : { "foos" : { "href" : "URI-to-foos" },"fooCreator" : { "href" : "URI-to-plain-fooWriter" } } }
在foo资源中包含指向fooWriter的链接:
foo资源:
{ "category" : "category chosen from an enumeration of possible categories","aRelatedResource" : "resource identifier from chosen from a collection","_links" : { "self" : {...},"fooEditor" : { "href" : "URI-to-fooWriter-initialized-for-current-foo" } } }
fooWriter看起来如下:
{ "fooPayload" : { "category" : "NULL or pre-initialized","color" : "NULL or pre-initialized","aRelatedResource" : "NULL or pre-initialized" },"_links" : { "fooPayloadDestination" : { "href" : "URI-to-foos-or-foo" },"categoryEnum" : { "href" : "URI-to-categories" },"colorEnum" : { "href" : "URI-to-colors" },"availableResourcesToRelateWith" : { "href" : "some-other-URI" },.... .... and even something useful for pre-validation etc. "validator" : { href : "URI-to-some-resource-or-service" } } }
总而言之,任何可以创建和编辑的资源都可能具有关联的编写器资源.
通过GET-ting编写器,用户代理可以以非常方便的方式创建/编辑资源.
嵌入在编写器中的有效负载被POST到其目的地,并且voilà:)
此外,应该有一个根容器,其中包含指向资源及其编写器的新资源的链接(请参阅上例中的fooRoot).
问题是……
……上面描述的模式有一个众所周知的名字吗?
…有没有更好的方法来解决创建/编辑问题,在创建/编辑时需要相邻资源,第三级成熟度仍然“保持”?
一些参考:
> The Hypermedia scale
> Richardson Maturity Model
> A REST API leveraging the hypermedia quite well
解决方法
在我看来,组织上面给出的示例的最简单方法是定义如下的根菜单:
GET / HTTP/1.1 Accept: application/hal+json ---- HTTP/1.1 200 OK Content-Type:application/hal+json { "_links" : { "plants" : { "href" : "/plants" } } }
植物关系将包含由给定媒体类型定义的植物资源集合(假设它是application / vnd.biology-example-org.plant):
GET /plants HTTP/1.1 Accept: application/hal+json ---- HTTP/1.1 200 OK Content-Type:application/hal+json { "_links" : { "self" : { "href" : "/plants" },"plant": [ { "href" : "/plants/parsnip","title" : "The Parsnip","type" : "application/vnd.biology-example-org.plant+json" } ] } }
要将新工厂添加到与防风草相关的集合中,POST到工厂收集资源并通过其链接与parnsip相关:
POST /plants HTTP/1.1 Content-Type: application/vnd.biology-example-org.plant+json { "title" : "The Carrot - a cousin of the Parsnip","category" : "vegetable","color" : "orange","related" : [ "/plants/parsnip" ] } ---- HTTP/1.1 201 Created Location: http://biology.example.org/plants/carrot
要随后修改胡萝卜,请对返回的URL发出PUT:
PUT /plants/carrot HTTP/1.1 Content-Type: application/vnd.biology-example-org.plant+json { "title" : "The Carrot - the orange cousin of the Parsnip","related" : [ "/plants/parsnip" ] } ---- HTTP/1.1 200 OK
上面的示例使用超文本应用程序语言(HAL)使用JSON传递“Level 3”REST语义. HAL简单而强大.我真正喜欢的一个约定是使用关系名称作为URI,当取消引用时,它直接指向关于该关系的文档以及它可以返回的资源.
如果您想使用这样的实时API,我强烈建议您查看HALtalk,它是HAL的现场演示API.