我对使用REST API构建Web服务感兴趣。我一直在阅读关于HATEOAS的内容,许多例子通过将它与人类上网时的做法进行比较来解释这个概念。这让我想到,为什么不以人类和机器都能轻易使用的方式构建REST API?
例如,我有一个小部件的内部模型,这个小部件具有部件号,价格等属性。当机器要求小部件列表时,我可以返回JSON表示。
{
widgets: [
{
id: 1,
part_number: "FOO123",
price: 100,
url: "/widget/1"
},
{
id: 2,
part_number: "FOO456",
price: 150,
url: "/widget/2"
},
{
id: 3,
part_number: "FOO789",
price: 200,
url: "/widget/3"
},
...
]
}
当一个人通过他/她的网络浏览器请求相同的列表时,似乎我应该能够采用相同的内部模型并对其应用不同的视图来生成HTML响应。 (当然,我会用其他页面元素装饰HTML响应,比如页眉,页脚等。)
这是一个明智的设计吗?为什么或者为什么不?有没有受欢迎的网站呢?
我看到的最大缺点是用户没有明显的方法来删除资源。在我的用例中,我不会让用户修改或删除资源,所以这不是一个交易破坏者,但一般来说你会如何处理?
答案 0 :(得分:6)
@mehaase
首先,我建议使用一种已注册的JSON超媒体格式:
所有这些都提供了用于创建具有语义链接关系的链接的显式语义。
例如,使用Collection(.next)+ JSON,您可以像这样表达您的小部件:
{"collection": {
"version": 1.0,
"items": [{
"href": "/widget/1",
"data": [{
"name": "id",
"value": 1,
"prompt": "ID"
}, {
"name": "part_number",
"value": "FOO123",
"prompt": "Part number"
}, {
"name": "price",
"value": 100,
"prompt": "Price"
}],
"links": [{
"rel": "self",
"href": "http://...",
}, {
"rel": "edit",
"href": "http://..."
}]
}]
}}
这为您提供了几个优势:
从示例中可以看出,它有足够的信息可以转换为HTML(或其他格式)。
我看到的最大缺点是用户没有明显的方法 删除资源。在我的用例中,我不会让用户 修改或删除资源,所以这不是一个交易破坏者,而是在 一般如何处理?
对于这个读取“编辑”链接关系规范,它意味着可以删除资源。
答案 1 :(得分:4)
你可以做几件事,但第一个前提是现代的“通用”网络浏览器真的很糟糕的REST客户端。
如果您的大多数交互都受到JavaScript的保护和管理,那么如果您编写“富客户端”,那么您可以说更多地依赖于JS生成的请求,而不仅仅是链接,表单和后退按钮,那么它可以成为更好的REST客户端。
如果你坚持使用表单和链接的通用浏览器体验,你可以通过重载POST来绕过缺少其他HTTP动词。你失去了中间人的一些保证。 DELETE是幂等的,POST不是,这有影响,但它不是毁灭性的,你只需要解决它。你可以用POST做幂等事,但中间人不会“知道”他们是,所以他们不能假设它是幂等的。
如果您最终不得不去“POST uber alles”,您将限制您的计算机客户端到同一个api,或者您提供并行服务 - POST愚蠢客户端使用的服务以及具有完整色域的其他服务可供他们使用。
也就是说,如果您选择基于XML的超媒体格式,那么您可以做的是将XSL转换添加到XML有效负载。浏览器将在有效负载上运行XSL,创建一个你喜欢的页面(页眉,页脚,足够的JS来扼杀马等),而机器将忽略它的这一方面,并专注于给定的数据。 / p>
在这方面给你一个“两全其美”。
答案 2 :(得分:1)
您始终可以构建REST API,然后围绕它构建自己的,人性化的Web应用程序。这是一种常见的做法,因为您具有开箱即用的功能和可扩展的开发人员系统。
答案 3 :(得分:0)
只需使用带有RDFa的HTML即可。因此人类可以读取HTML并且机器可以读取RDFa注释。你需要像hydra这样的REST词汇来注释链接,以及其他词汇,比如schema.org来注释内容。
为不同类型的客户端使用不同媒体类型的另一种选择,例如人类的HTML和机器的JSON-LD。