19

对于复杂的 Web 应用程序,一个页面视图可能需要许多不同类型的数据。如果您正在执行客户端模板化并从 RESTful Web 服务中提取此数据,您可能需要发出大量请求来填充页面。是否有任何约定可以组合 REST 请求,以接收包含所有所需响应的单个有效负载?

以 Stack Exchange 用户页面为例,您可能需要至少从Stack Exchange API调用这些来构建页面:

  • /用户/{id}
  • /users/{id}/answers
  • /users/{id}/声誉
  • /users/{id}/tags
  • /users/{id}/问题
  • ...ETC

此类 API 的提供者能否允许您通过单个请求获取所有数据? 特别是如果涉及其他根类型,假设您还必须请求 /revisions/{id} 和 /tags 来构建页面也出于某种原因。

需要明确的是,我不想知道是否可以在 Web API 中提供这样的功能——我想知道是否有标准的或至少记录在案的方法来这样做。

4

4 回答 4

5

我认为我们需要一些标准的方式来做到这一点,但在那之前,你可能只能靠自己了。

过去,当我想做跨多个资源的交易时,我也遇到过类似的挑战。我发明了新的资源,更清楚地描述了我将要进行的操作(从账户 A 中减去 5 并在账户 B 中添加 5 成为与 from 和 to 成员的交易)。

也许可以通过使用另一个 REST 调用作为容器来应用类似(但更通用)的方法;

POST /batchRequests { requests: [
    { method: 'POST', url: '/resource', payload: { ... } }
], transactional: false }

这反过来又返回了一个包含结果的“BatchRequest”对象。这与 Facebook 所做的非常接近。

于 2013-08-07T10:55:27.703 回答
3

我认为这可能违反 REST 原则,不是吗?即每个对象表示的唯一 URI 及其有效负载。这不会让事情变得更糟吗?鉴于它不是 TI 计算器,而是一台能够并行 HTTP 请求的现代计算机,而一台计算机则需要尽可能长的时间。

不要认为有一个标准,但这里有一个例子——https://developers.facebook.com/docs/reference/api/batch/

于 2013-01-31T22:51:19.557 回答
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;"

当前是Accept HTTP-Header字段,它告诉服务器要使用哪个版本和哪个内容类型。

为了保持浏览器或代理缓存功能,我决定在我的 api 上返回Vary HTTP Header字段,其中所有内容都在更改HTTP-Headers,以便浏览器可以通过uri 和 headers正确区分资源。

Vary: "Accept, Accept-Language"

最大的问题是,如何组合资源以防止客户端一次打开过多的 tcp 连接。

例如:如果您通过/user从我的 API 查询用户列表,API 将返回所需内容类型(JSON、XML、HTML)的用户对象数组。

我不会详细介绍,因为有可用的分页和过滤器/搜索支持。

每个用户对象都具有依赖资源,例如朋友和/或消息

有一个非常好的结构化标准,称为HAL(超文本应用程序语言),它提供了一些简单的方法来将资源与其相关资源链接资源结合起来。它使用 JSON 来表示数据。

看看Mike Kellyhttp://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 连接进行查询。

我知道保持活动连接还有其他问题,因此请随时与我讨论所有想法。

谢谢!

于 2014-05-06T14:56:10.640 回答
1

我参加这个聚会很晚了,但我一直在网上寻找一些关于平衡干净的 REST 设计与实际网站的现实的话题。我发现了通常的“减少对性能的 http 请求”,但没有关于良好实践的好文章,着眼于权衡。(评论者可以随意给我指出一个方向!)什么鬼,还没有明显的答案。

不确定您是在问其他人是否有可能通过这样做让您的生活更轻松,或者您是否因为您正在设计 API 而问。你的问题说其他人所以我们开始吧。

此类 API 的提供者能否允许您通过单个请求获取所有数据?特别是如果涉及其他根类型,假设您还必须请求 /revisions/{id} 和 /tags 来构建页面也出于某种原因。

需要明确的是,我不想知道是否可以在 Web API 中提供这样的功能——我想知道是否有标准的或至少记录在案的方法来这样做。

简短版:我还没有看到很多关于这个主题的好文章。REST 的流行可能还很年轻,因为它有一套好的学术共识风格的答案。在我可以摆脱它的地方,我会做我必须做的事情,并且我不太担心我的设计是多么纯粹:像 REST 这样的首字母缩略词。但是,如果我是大型公共 API 的提供者(见下文),我可能会偏向更纯粹的标准(再次,例如 REST)实现。

这是可能的,而且我已经在我自己的应用程序中玷污了许多纯 REST 设计,以实现我在性能方面所需要的。主要是 RPC 或组合资源获取/更新,以最大限度地减少 HTTP 请求的数量,成为现代科学怪人 Web 开发人员可能产生的东西。

此类 API 的提供者能否允许您通过单个请求获取所有数据?

从技术上讲,他/她当然可以做到这一点。但如果我是一个流行的、面向公众的 API 的发布者,我可能会使用更“纯”的 REST 方法,因为如果有很多陌生人会使用它,那么简单性、可用性和维护现在就具有全新的意义。在这种情况下,对于我和消费者而言,性能的优先级可能低于我既是消费者又是提供者的企业应用程序。

像往常一样,开发人员必须在实现速度、简洁设计、可维护性、性能和无数其他事情之间做出适当的平衡。(这个决定已经从选择语言开始——Python/Ruby vs Java/C# vs C++ vs...)

于 2014-09-16T17:20:27.677 回答