对于复杂的Web应用程序,一个页面视图可能需要许多不同类型的数据。如果您正在进行客户端模板化并从RESTful Web服务中提取此数据,则可能必须提出大量填充页面的请求。是否存在可以组合REST请求的约定,以接收包含所需响应的单个有效负载?
要使用“堆栈交换用户”页面作为示例,您可能需要至少调用the Stack Exchange API中的这些来构建页面:
此类API的提供商是否允许您通过单个请求获取所有数据? 特别是如果涉及其他根类型,则说出由于某种原因,您还必须请求/修订/ {id}和/ tags来构建页面。
要明确,我不想知道它是否可能在Web API中提供此类功能 - 我想知道是否存在标准或至少有文档记录的方法如此。
答案 0 :(得分:5)
我认为我们需要一些标准的方法来做到这一点,但在那之前,你可能是你自己的。
过去,当我想要跨多个资源进行交易时,我遇到了类似的挑战。我发明了新的资源,描述了我要做的更明确的行动(从帐户A中减去5,在帐户B中添加5成为与成员之间的交易)。
通过使用另一个REST调用作为容器,也许可以在这里应用类似的(但更通用的)方法;
POST /batchRequests { requests: [
{ method: 'POST', url: '/resource', payload: { ... } }
], transactional: false }
然后返回包含结果的“BatchRequest”对象。它与Facebook的表现非常接近。
答案 1 :(得分:3)
我认为这可能违反REST原则,不是吗?即每个对象表示的唯一URI及其有效负载。它不会让事情变得更糟吗?鉴于它不是TI计算器,而是能够并行HTTP请求的现代计算机与单个HTTP请求相比,只要它们的最大值就可以了。
不要认为有标准,但这是一个例子 - https://developers.facebook.com/docs/reference/api/batch/
答案 2 :(得分:1)
我知道我很晚,但也许我的想法可以帮助别人......
我的解决方案有点不同。
我将资源存储在每个资源的单个uri(统一资源标识符)中。
用户强>
GET /user => INDEX
PUT /user => CREATE (RETURN LOCATION HEADER)
GET /user/{id} => FIND
POST /user/{id} => UPDATE
DELETE /user/{id} => REMOVE
讯息强>
GET /user/{id}/message => INDEX
PUT /user/{id}/message => CREATE (RETURN LOCATION HEADER)
GET /user/{id}/message => FIND
POST /user/{id}/message/{id} => UPDATE
DELETE /user/{id}/message/{id} => REMOVE
<强>友强>
GET /user/{id}/friend => INDEX
PUT /user/{id}/friend => CREATE (RETURN LOCATION HEADER)
GET /user/{id}/friend => FIND
POST /user/{id}/friend/{id} => UPDATE
DELETE /user/{id}/friend/{id} => REMOVE
生成的内容类型可以通过 HTTP-Header 进行更改,客户端需要指定。
Accept: "application/vnd.com.example.api+json; version: 1.0;"
目前,接受HTTP-Header 字段告诉服务器使用哪个版本和哪种内容类型。
为了保留浏览器或代理缓存功能,我决定在我的api上返回 Vary HTTP Header 字段,其中包含所有内容更改 HTTP-Headers,所以浏览器可以通过 uri和标题来正确区分资源。
Vary: "Accept, Accept-Language"
最大的问题是,如何组合资源以防止客户端同时打开过多的tcp连接。
例如:如果您通过 / user 从我的API查询用户列表,API将返回所需内容类型(JSON,XML,HTML)的用户对象数组。 / p>
我不会详细介绍,因为可以使用分页和过滤/搜索支持。
每个用户对象都有相关资源,例如朋友和/或消息。
有一个非常好的结构化标准,称为 HAL (超文本应用程序语言),它提供了一些简单的方法来将资源与其依赖资源或链接资源相结合。它使用JSON来表示数据。
通过 Mike Kelly 查看http://stateless.co/hal_specification.html。
但是该解决方案也没有在一次调用中组合资源,它只是将依赖或链接资源的uri与有效负载一起发送给客户端。
这将让客户决定显示哪些其他信息。
当然,所有非常重要的缓存功能都在起作用。
在浏览资源时,大多数流量都是可以缓存的重复请求。
如果给出的示例想要在用户列表中显示朋友的数量或用户的消息数量,请考虑将依赖资源添加为结果的关键字。
示例用户响应(JSON)
{
id: 1,
email: test@test.com,
...
friends: {
count: 1,
_links: [{
'id': '2',
'name': 'Peter Parker',
'uri': '//api.example.com/user/2'
}]
},
messages: {
count: 1,
_links: [{
'id': 'x4gZ6',
'subject': 'Testmessage',
'uri': '//api.example.com/user/1/message/x4gZ6'
}]
},
...
}
现在让我们谈谈如何防止使用多个TCP连接!
有一个非常简单和好的方法...
为什么不使用:
Connection: "keep-alive"
这将使客户端可以根据需要一次查询尽可能多的资源。 通过与服务器的单个TCP连接查询所有资源。
我知道保持连接存在其他问题,所以请随时与我讨论所有想法。
谢谢!
答案 3 :(得分:1)
我参加这个聚会的时间已经很晚了,但是我一直在寻找一些关于平衡干净的REST设计与实际网站现实的主题。我发现了通常的&#34;减少http请求的性能&#34;但是没有关于良好实践的好文章,着眼于权衡。 (评论者可以随意指出我的方向!)到底是什么,没有明显的答案。
不确定您是否可以通过这样做来询问其他人是否可以让您的生活更轻松,或者您是否因为您正在设计而要求一个API。你的问题是其他人,所以我们走了。
此类API的提供商是否允许您通过单个请求获取所有数据?特别是如果涉及其他根类型,请说您还必须出于某种原因请求/ revision / {id}和/ tags来构建页面。
要明确,我不想知道是否可以在网络API中提供此类功能 - 我想知道是否有标准或至少有文档证明这样做的方法
简短版本:我还没有看到很多关于这个主题的好文章。 REST的受欢迎程度可能还很年轻,但需要一套好的学术共识风格的答案。在我可以侥幸逃脱的地方,我会做我必须做的事情,而不用担心我的设计是多么纯粹:像REST一样的缩写。但如果我是一个大型公共API的提供者(见下文),我可能会错误地采用更纯粹的标准(例如REST)实现。
这是可能的,我在自己的应用程序中玷污了许多纯REST设计,以实现我在性能方面所需要的。主要是RPC或组合资源获取/更新,以最大限度地减少HTTP请求的数量,成为现代科学家网络开发人员可能产生的东西。
此类API的提供商是否允许您通过单个请求获取所有数据?
技术上他/她当然可以做到这一点。但如果我是一个受欢迎的,面向公众的API的发行商,我可能会使用更多纯粹的&#34; REST方法,因为如果许多陌生人将使用它,简单性,可用性和维护现在具有全新的意义。对于我和消费者而言,在这种情况下,性能可能低于我同时为消费者和提供商的企业应用程序。
与往常一样,开发人员必须在实施速度,清洁设计,可维护性,性能和其他许多事情之间做出适当的平衡。 (这个决定已经开始选择语言 - Python / Ruby vs Java / C#vs C ++ vs ...)