我对使用 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 响应,如页眉、页脚等。
这是一个明智的设计吗?为什么或为什么不呢?有没有真正这样做的热门网站?
我看到的最大缺点是用户没有明显的方法来删除资源。在我的用例中,我不会让用户修改或删除资源,所以这不是一个交易破坏者,但总的来说,你会如何处理这个问题?
> @mehaase
首先,我建议使用已注册的JSON超媒体格式之一:
- 集合+JSON:http://amundsen.com/media-types/collection/format/
- Collection.next+JSON:http://code.ge/media-types/collection-next-json/
- HAL - 超文本应用语言:http://stateless.co/hal_specification.html
它们都提供了显式语义,用于创建具有语义链接关系的链接。
例如,使用 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://..."
}]
}]
}}
这为您提供了几个优势:
- 您无需重新发明轮子来指定链接
- 您可以自由使用所有已注册的链接关系类型:http://www.iana.org/assignments/link-relations/link-relations.xml
- 根据您的数据结构,您可以轻松使用上述格式的集合/项目语义
- 如果需要,您也可以描述输入表单
正如你从例子中看到的,它有足够的信息来转换为HTML(或其他格式)。
我看到的最大缺点是用户没有明显的方法 以删除资源。在我的用例中,我不会让用户 修改或删除资源,因此这不是交易破坏者,而是在 一般你会如何处理?
对于此读取"编辑"链接关系规范,它意味着可以删除资源。
你可以做几件事,但第一个前提是现代的"通用"Web浏览器真的是糟糕的REST客户端。
如果你的大部分交互都是由JavaScript保护和管理的,如果你写了一个"富客户端",可以说你更多地依赖于JS生成的请求,而不仅仅是链接,表单和后退按钮,那么它可以是一个更好的REST客户端。
如果您坚持使用表单和链接的通用浏览器体验,则可以通过重载 POST 来绕过缺少其他 HTTP 谓词的问题。你失去了中介机构的一些保证。DELETE 是幂等的,POST 不是,这会产生影响,但它不是毁灭性的,你只需要解决它。你可以用 POST 做幂等的事情,但中介不会"知道"它们是幂等的,所以他们不能假设它是幂等的。
如果你最终不得不去"POST uber alles",你要么将你的机器客户端限制在同一个api上,要么提供并行服务——那些由POST愚蠢的客户端使用,以及其他那些拥有全部可用范围的服务。
也就是说,如果您选择基于 XML 的超媒体格式,那么您可以做的是将 XSL 转换添加到 XML 有效负载。浏览器将在有效负载上运行 XSL,创建您喜欢的漂亮页面(页眉、页脚、足够的 JS 来窒息马等),而机器将忽略它的这一方面,只关注给定的数据。
在这方面为您提供"两全其美"。
您始终可以构建 REST API,然后围绕它构建自己的、人性化的 Web 应用程序。这是一种常见做法,因为您具有开箱即用的功能和面向开发人员的可扩展系统。
将HTML与RDFa一起使用即可。因此,人类可以阅读HTML,机器可以阅读RDFa注释。你需要一个像 hydra 这样的 REST 词汇来注释链接,以及其他词汇,如 schema.org 来注释内容。
为不同类型的客户端使用不同媒体类型的另一种选择,例如用于人类的 HTML 和用于机器的 JSON-LD。