REST Web 服务版本控制

2023年 9月 2日 104.9k 0

管理 API 的更改很困难。对于曾经维护过任何类型 API 的人来说,这并不奇怪。Web 服务是 API 的一个特例,与其他类型的 API 一样,很容易受到版本控制方面的许多困难的影响。对于基于 HTTP 的 REST 样式 Web 服务,可以使用资源和内容协商的组合来缓解与 API 版本控制相关的大多数问题。

假设您有一个包含一些帐户资源的 REST/HTTP Web 服务。假设您可以提出这样的请求:

===>
GET /accounts/3 HTTP/1.1
Accept: application/vnd.mycompany.myapp+xml
<===
HTTP/1.1 200 OK
Content-Type: application/vnd.mycompany.myapp+xml
<account>
<name>Inigo Montoya</name>
</account>

首先,您可能注意到我的示例使用供应商 MIME 媒体类型来描述表示形式。使用更通用的 MIME 媒体类型(例如)application/xml更为常见,至少根据我的经验。使用通用媒体类型是完全合法的,但有点愚蠢。您实际上并不是在请求任何旧的 XML 文档,而是在请求具有非常具体的架构的 XML 文档。除了我的理想主义咆哮之外,使用特定的媒体类型还有一些强大的实际好处,这是本文的核心。

向后兼容的更改

通常需要进行更改以公开系统的新行为,而这些新行为不会对正确实现的客户端产生负面影响。例如,您想开始跟踪帐户的电子邮件地址。如果application/vnd.mycompany.myapp+xml格式文档明确指出应忽略无法识别的元素,您可以简单地将电子邮件元素添加到帐户表示中。

<account>
<name>Inigo Montoya</name>
<email-address>mailto:prepare-to-die@youkilledmyfather.example</email-address>
</account>

在添加电子邮件元素之前创建的任何客户端都将忽略它的存在。问题解决了。

不兼容的更改

不幸的是,并非所有更改都可以以向后兼容的方式实现。例如,在向帐户添加电子邮件几个月后,销售团队签署了一项价值 1 亿美元的交易。但新客户要求每个帐户都可以拥有多个电子邮件地址。经过思考一段时间后,您决定公开这一点的最佳方法是更改​​帐户表示形式,如下所示。

<account>
<name>Inigo Montoya</name>
<email-addresses>
<email-address priority=&#39;1&#39;>mailto:prepare-to-die@youkilledmyfather.example</email-address>
<email-address priority=&#39;2&#39;>mailto:vengeance@youkilledmyfather.example</email-address>
<email-address>
</account>

当然,这将打破任何期待旧格式的客户——几乎所有客户。这是我们可以进行内容协商的地方。您可以简单地定义一种新的媒体类型(例如application/vnd.mycompany.myapp-v2+xml)并将新的多电子邮件格式与其关联。然后,客户可以请求他们想要的任何格式。老客户不知道新的媒体类型,因此他们只能使用旧的单一电子邮件格式。

===>
GET /accounts/3 HTTP/1.1
Accept: application/vnd.mycompany.myapp+xml
<===
HTTP/1.1 200 OK
Content-Type: application/vnd.mycompany.myapp+xml
<account>
<name>Inigo Montoya</name>
<email-address>mailto:prepare-to-die@youkilledmyfather.example</email-address>
</account>

新客户确实了解新媒体类型,因此他们可以访问新功能。

===>
GET /accounts/3 HTTP/1.1
Accept: application/vnd.mycompany.myapp-v2+xml
<===
HTTP/1.1 200 OK
Content-Type: application/vnd.mycompany.myapp-v2+xml
<account>
<name>Inigo Montoya</name>
<email-addresses>
<email-address priority=&#39;1&#39;>mailto:prepare-to-die@youkilledmyfather.example</email-address>
<email-address priority=&#39;2&#39;>mailto:vengeance@youkilledmyfather.example</email-address>
<email-address>
</account>

每个人都得到他们需要的东西。易如反掌。

替代方法

如今,最常提出的 REST/HTTP Web 服务接口版本控制方法似乎是通过插入版本来破坏 URI。例如,

http://foo.example/api/v1/accounts/3

我真的很讨厌这种方法,因为它意味着一个版本的 API 中的帐户实际上与不同版本的 API 中的帐户是不同的资源。

它还迫使客户做出艰难的选择:要么同时支持多个版本的 API,要么打破 REST 的核心限制之一。例如,假设存在 v1 API 的客户端,该客户端将引用(包含版本指示符的 URI)保存到帐户。一段时间后,客户端会更新以支持新版本的 API。在这种情况下,客户端可以同时支持两个版本的 API,因为所有先前存储的 URI 都指向旧版本的 API,或者它必须将已存储的所有 URI 合并到新 API 的点。修改所有 URIS 会破坏REST 的HATEOAS约束,并且支持 API 的多个版本是维护的噩梦。

结论

REST/HTTP Web 服务接口的更改具有三种基本风格:与资源类型关联的属性的更改、新类型资源的添加以及过时资源类型的弃用。如果您遵循REST 的HATEOAS约束,则可以使用此处描述的方法安全地处理所有三种情况。

这种方法确实导致了媒体类型的创建,但媒体类型很便宜,所以我们可以——而且应该——拥有我们需要的尽可能多的媒体类型。如果使用得当,内容协商可用于解决与 REST/HTTP Web 服务接口版本控制相关的问题。

相关文章

LeaferJS 1.0 重磅发布:强悍的前端 Canvas 渲染引擎
10分钟搞定支持通配符的永久有效免费HTTPS证书
300 多个 Microsoft Excel 快捷方式
一步步配置基于kubeadmin的kubevip高可用
istio全链路传递cookie和header灰度
2023 年最适合 Windows 11 使用的 20 个应用

发布评论