选择您自己的代表

通过提供相同数据的多种表示,HTTP API可以对客户端更友好

当客户端从API请求数据时,它可能只需要可用字段的子集,但是许多API仅提供可用数据的单一表示。 我们可以使用内容协商,而不仅仅是在json或xml(或其他)之间进行选择,并提供客户要求的内容。

样本API

许多应用程序使用属于用户的项目集合的概念,因此在这里我们将使用喜欢的颜色的集合。

我们可以使用长颈鹿在F#中定义一个简单的my-colors端点:

这定义了一个Color类型,其中包含一些不同的属性,并通过GET请求使它们的集合可用。 它返回一个硬编码的值列表,但这只是一个示例,这样就可以了。

我们还可以创建一个简单的客户端,以从端点检索数据并将其显示给最终用户。 快速代码示例是使用URLSessionDecodable协议的iOS应用程序的一部分,使事情变得简单:

这种方法效果很好,但是我们已经可以看到API提供的数据与客户端实际需要的数据之间存在不匹配-API返回了一堆客户端不需要关心的字段。 对于此示例API来说,这不是什么大问题,但是如果列表中有很多条目或者我们的颜色对象更复杂,则可能会成为问题。 幸运的是,我们有一些方法可以使我们的API与客户需求相匹配。

一种新的媒体类型

我们不能仅仅从API响应中删除值,因为可能还有其他客户端依赖该数据,但是如果我们为客户端提供一种请求其他响应的方式,那么我们可以为每个客户端提供一个包含其数据的响应需要。

首先,我们需要配置Giraffe以支持自定义媒体类型。 为此,我们不需要任何自定义序列化,因此我们可以使用已经配置的json序列化器。

然后,我们可以创建颜色的自定义表示,并从端点向要求迷你版本的客户端返回它。

通过将我们的API配置为将迷你颜色响应返回给请求它的客户端,我们可以更新我们的应用程序客户端以发送新的Accept标头。 方便地,对于我们的快速客户端,设置额外的标头很简单:

现在,我们的客户请求一个特定的响应,而我们的API提供了响应,这非常好……目前。 但是,这的确会使我们的API和客户端耦合在一起-如果将来客户需要更改,那么即使已经可以提供该字段,我们的API也将需要更新,我们唯一的选择是全部或全部。

询问我们需要什么

我们希望找到一种方法,使我们的客户可以根据需要调整从API获取的数据, 而无需更改API 。 这意味着我们将需要某种方式让客户端描述其希望从API接收的数据。

现有几种描述API应该返回给客户端的数据形状的方法,尤其是GraphQL和JSON:API,因此值得考虑如何以不必将我们与任何特定事物联系在一起的方式来实现它如果以后要更改首选项,或者特别是在我们拥有具有不同需求的不同API客户端的情况下,请在将来实施。

内省的ReST建议使用MicroType作为构成媒体类型的一种方式。 使用该方法,我们现在可以添加一种过滤方法,然后在不破坏任何客户端的情况下,在以后添加对不同方法的支持。 因此,我们需要进行以下更改:

切换我们的API以使用可以支持过滤的媒体类型

我们将使用一种通用的api媒体类型: application / vnd.chamook.api + json ,它可以在与此API连接的所有api上使用。 我们不使用诸如application / json之类的东西,因为我们不能保证返回简单旧json的API将支持过滤(或我们想要添加的任何其他功能)。

定义我们的客户可以使用的过滤语法

我们可以使用前面提到的一种奇特的选择。 但是现在我们只需要一个非常简单的过滤器,因此自定义字段列表可能会更易于实现。 因为我们使用的是MicroType,所以如果以后确实需要,我们总是可以在以后添加对GraphQL之类的支持。

更新我们的客户端以使用新的过滤方法

完成此更新后,我们的客户端和API应该很好地分离,以便将来对过滤进行任何更改。

我们可能会增加API来描述客户端可用过滤选项的方式,但是如果我们不想使用该API的ReSTful方法,我们可以将其保留为文档中包含的内容-只要我们在API表面遵循通用约定,就不会有太大问题。

最终表格

做出决定后,我们可以使用以下代码更新API(使用最简单的过滤方法,通过指定响应中应包含哪些字段作为媒体类型的参数):

我们的客户只需要稍作更改即可使用新版本:

现在,我们的客户可以准确地指定所需的字段,并且我们的API将做出适当的响应。 仍然有一些可以改进的地方,但是到目前为止已经足够了。

API的源代码和应用程​​序客户端可在GitHub上获得。

这最初发布在这里。