【问题标题】:Forcing web api consumers to accept new fields in responses强制 web api 消费者在响应中接受新字段
【发布时间】:2012-02-07 13:16:06
【问题描述】:

我正在创建现有 RESTful Web api 的 v2。

响应是 JSON 对象列表,大致格式如下:

[
  {
     name1=value1,
     name2=value2,
  },
  {
     name1=value3,
     name2=value4,
  }
]

我们在 v1 中观察到的一个问题是,一些客户端将按整数位置访问字段,而不是按名称。这意味着,如果我们决定在响应中添加字段(我们最初认为这是一种保持兼容性的更改),那么我们客户端的一些代码就会中断,除非我们在最后添加字段。即便如此,其他客户端的代码还是会中断,因为它们会在遇到意外的属性名称时以某种方式失败。

为了在 v2 中解决此问题,我们正在考虑对每个响应中的字段进行随机重新排序。这将强制客户端按名称而不是按位置索引字段。

此外,我们正在考虑为每个响应添加一个随机命名的字段。这将迫使客户忽略他们无法识别的字段。

虽然这听起来有些晦涩难懂,但它确实具有我们能够添加新字段的优势,因为我们知道这不会破坏任何客户端。这意味着我们可以在同一个 URL 上发布对 v2.1、v2.3 等的兼容更新,这意味着我们只需要维护和支持较少数量的 API 版本。

另一种方法是在新 URL 上发布破坏兼容性的 v3、v4,这意味着我们将不得不维护和支持许多不兼容的 API 版本,这将使我们变得更薄。

这是一个坏主意,如果是,为什么?我应该考虑其他类似的想法吗?

更新: 前几个回复指出,如果我记录了问题(即在文档中指出可能会添加或重新排序字段),那么如果客户端代码出现问题,我将不再受到责备当我随后添加或重新排序字段时中断。遗憾的是,我认为这对我们来说不是一个合适的选择:许多组织依赖我们 API 的功能来进行具有重大财务影响的实际交易。这些组织不是以技术为导向的——在客户端的最终实现涵盖了整个技术熟练度范围。我们已经确实记录了字段可能会在 v1 的文档中添加或重新排序,这显然不起作用,因为现在我们不得不发布 v2,因为许多客户,由于时间不足或经验或能力,当我们添加新字段时,仍然编写会中断的代码。如果我现在向界面添加字段,它会破坏十几个不同公司的界面,这意味着他们(和我们)每分钟都在流血。如果我拒绝恢复更改或修复它,说“他们应该阅读文档!”,那么我很快就会失业,这是正确的。我们可能会尝试教育“失败”的合作伙伴,但这注定会失败,因为随着我们的不断发展,问题每个月都会变得越来越大。我的问题是,无论客户试图做什么,我是否可以系统地解决整个问题,防止这种情况发生?如果我建议的技术可行,我为什么不使用它们?为什么其他人不使用它们?

【问题讨论】:

  • 我的观点是,如果您的文件明确表明订单没有保证,并且可以随时添加新字段,如果在这种情况下中断是客户的错。
  • 我理解这种观点,但我认为这不是我们的选择。我们有许多商业利益使用我们的界面进行具有实际财务影响的交易。如果我在没有通知或通知的情况下破坏了数十家不同公司与我们长期存在的接口,然后拒绝修复它,并说“他们应该阅读文档!”那么我很快就会失业,这是正确的。这个问题的重点是如何减少这种情况出现的频率。

标签: rest compatibility backwards-compatibility asp.net-web-api


【解决方案1】:

如果您希望您的媒体类型“可进化”,请在文档中明确说明这一点。同样,如果不能保证字段的放置顺序,也要明确说明。如果您为 API 提供示例代码,请确保它不依赖于字段排序。

但是,即使假设您必须维护不同版本的媒体类型,您也不必对 URI 进行版本控制。 REST 使您能够维护相同的版本无关 URI,但使用 HTTP 内容协商(通过 AcceptContent-Type 标头)在同一 URI 上提供不同的有效负载。

因此,任何不明确希望接受您的新 v2/v3/etc 编码的客户端都不会得到它。默认情况下,您可以使用原始字段排序返回旧的 v1 编码,所有这些脆弱的客户端应用程序都可以正常工作。但是,新的客户端开发人员会知道(感谢您的文档)通过Accept 表明他们愿意并且能够看到新字段并且他们不关心他们的订单。最重要的是,您可以(并且应该)始终使用相同的 URI。请记住 - 像这样的不同有效负载只是相同底层资源的不同表示,因此 URI 应该是相同的。

【讨论】:

  • 感谢有关“接受”和“内容类型”的指针以重载相同的 URI,很高兴知道。不过,我对此有所保留,但我将在上面的原始问题中澄清这一点……干杯!
  • 嗯,我没有在更新的问题中真正解释我的保留意见,是吗?它们是:您的建议似乎让我找到了一种更简单的方法来发布更多版本的 API,所有版本都共享相同的 URL。我同意这太棒了。但是,我的问题是,我能否使用所描述的技术来减少我必须首先生产、支持和维护的新 API 版本的数量?
  • 顺便提一下,我们确实提供了示例代码,但仅使用 Python,而且消费者使用多种不同的语言,因此大多倾向于编写自己的解决方案。
【解决方案2】:

我决定最大限度地使用所描述的技术。我没有听到任何反对他们对我有用的反对意见。 Brian 的回答,关于为不同的 API 版本重新使用相同的 URI,是一个可靠且备受赞赏的补充想法(赞成),但我不能授予它“最佳答案”,因为它没有达到核心我原来的问题。

【讨论】:

  • 我认为您想到了一个简单而有效的解决方案。我只是希望排序列的开销不会太大
  • 5年后的反馈:效果很好,一有机会就再做一次。幸运的是,重新排序字段的开销很小:例如,随机排序比排序便宜得多,而且服务器上的所有这些操作都比我们完成的数据库访问快很多数量级,然后发送结果通过 Internet 响应客户端。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-31
  • 2023-03-31
  • 2020-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多