我正在尝试设计一个可以充分利用超媒体的RESTful服务。
最好,用户代理应该只知道根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",
"color" : "color chosen from an enumeration of possible colors",
"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" }
}
}
综上所述,可以创建和编辑的任何资源都可以具有关联的编写器资源。
通过获取写入程序,用户代理可以以非常方便的方式创建/编辑资源。
嵌入在编写器中的有效负载被POST-ed到其目的地和地址:)
此外,应该有一个根容器,其中包含指向资源及其写者的新资源链接(请参见上面示例中的fooRoot)。
问题是...
...上述模式是否有众所周知的名称?
...是否有更好的方法来解决创建/编辑问题,即在创建/编辑时需要相邻资源,而成熟度的第三级仍然“保持”?
一些参考:
The Hypermedia scale
Richardson Maturity Model
A REST API leveraging the hypermedia quite well
最佳答案
您所描述的内容使我想起了create and edit form link relations。但是,如果您要构建一个API,那么它的使用就会受到很大的限制,因为无论定义方式如何,都需要有人对其进行编程。
我认为,组织以上示例的最简单方法是定义一个如下所示的根菜单:
GET / HTTP/1.1
Accept: application/hal+json
----
HTTP/1.1 200 OK
Content-Type:application/hal+json
{
"_links" : {
"plants" : { "href" : "/plants" }
}
}
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"
}
]
}
}
要将新植物添加到与防风草相关的集合中,请发布到
plants
集合资源并通过其链接与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",
"category" : "vegetable",
"color" : "orange",
"related" : [ "/plants/parsnip" ]
}
----
HTTP/1.1 200 OK
上面的示例使用超文本应用程序语言(HAL)通过JSON传达“ Level 3” REST语义。 HAL简单但功能强大。我真正喜欢的一种约定是使用关系名称作为URI,当解除引用时,它直接指向有关该关系及其可以返回的资源的文档。
如果您想使用这样的实时API,我强烈建议您查看HALtalk,它是HAL的实时演示API。