老旧的API,你应该如何处理?

废弃 API 端点是一项很是具备挑战性的工做,咱们须要考虑全部依赖该 API 的客户端,避免出现级联的故障。针对该问题,有两个新的 HTTP 头信息草案,本文详细阐述了该如何使用这两个新的头信息安全地关闭 API。

 

万物都会有终结,HTTP API 也不例外。不论你的 API 今天看上去多么伟大,早晚有一天你会想发布一个全新的版本,新版本能更好地解决相同问题,在各方面可能都会有所改善,可是它由于有了新参数,与旧版本也没法兼容,或者你只是想完全关闭旧的 API。总而言之,你如今的 API 不会永远存在。html

可是,这并不是垂手可得就能完成的,由于你的 API 有客户端。若是你关闭端点、参数或整个 API 而没有作出恰当的警告的话,那他们确定会很是不爽。前端

那么,该怎样安全地关闭 API,让你的用户尽量地感到轻松愉快呢?git

在这方面,咱们有正确的作事方式,包括两个新的头信息草案,它们正在被新的 IETF “Building Blocks for HTTP APIs”工做组进行标准化,旨在造成一个精确的过程。咱们了解一下。github

1. 制定计划

初始第一步:检查相关的 API 是否真的有客户端。web

但愿你能有某些 API 的度量指标,至少在某些地方存有日志。若是没有的话,那把它们添加上,若是你有这些东西的话,而且你能肯定没有人再使用这个 API 了,那么恭喜你,你赢了。如今,你就能够把它关掉,删掉代码,不要再管这篇文章了,好好睡一觉。api

下一个问题,若是比较遗憾,你没法去睡觉的话,那就要问问本身,除了关闭这个 API,还有没有其余方案。你关闭的全部东西都有可能破坏别人的代码,而且会消耗他们的时间来修复这些问题。若是 API 能继续运行的话,对客户端的生态系统和整个 web 的健康都是有好处的。缓存

在不少场景下,旧的 API 能够在内部进行转换,透明地转化成对新 API 的调用,这样能够避免维护两个彻底独立的版本。这是 Stripe 的 API 版本管理方式的一个基本组成部分,他们在全部发生变化的 API 中都包含了转换,以确保对不兼容的旧版本 API 的请求能继续像之前那样运行,根据须要自动转换请求和响应从而可使用较新的代码。安全

https://stripe.com/blog/api-versioning#versioning-under-the-hoodide

这样的转换并不老是可行的,并且若是永远这样作的话会带来明显的额外复杂性,可是若是你能够作到这一点的话,就能为用户提供很是有价值的稳定性,而且能够节省大量废弃旧版本或维护旧版本相关的工做。工具

可是,若是这个服务 / 端点 / 参数已经用到了生产环境,并且继续支持它是不现实的作法,那么它必需要被淘汰。

要实现这一点,咱们就要有一个计划。咱们首先要问本身三个关键的问题:

你但愿用户该怎么作?常见的答案包括:升级到相关功能的一个更新的、依然能获得支持的版本;使用一些可替代的端点 / 参数 / 服务;使用不一样的服务,它们与你无关,不须要你关心。

用户应该什么时候迁离这个 API?你所提出的替代方案如今就能够用了吗?

截止时间是何时?也就是,这个 API 什么时候会彻底中止使用?(若是不能彻底肯定的话,你能够稍微延迟回答这个问题)。

计划准备就绪以后,咱们就该把它告诉人们了。

2. 沟通

首先,要把这一决定告诉人们。

发邮件到邮件列表,在 Twitter 或微博上发帖,若是有 API 规范的话,对其进行更新(好比,OpenAPI 在 operations 和 parameters 上有一个deprecated字段),并在相关的在线文档上大声强调这一点。

你应该包含上文提到的全部信息:他们应该作些什么做为替代方案,你建议他们何时开始迁移以及他们必需要进行迁移的最后期限(若是已经肯定期限的话)。

在将这些信息告诉给人们后,接下来就该告诉计算机,而这就是新的 IETF 头信息能够发挥做用的地方。

Deprecation 头信息

Deprecation 头信息能告诉客户端请求的资源如今依然像之前那样运行,可是这种方式已经再也不推荐使用了。

https://datatracker.ietf.org/doc/draft-ietf-httpapi-deprecation-header/?include_text=1

经过一个简单的 HTTP 头信息,咱们就能够声明这一点:
Deprecation: true
另外,咱们还能提供一个日期。这个日期告诉用户他们什么时候该开始进行迁移。这个日期能够是一个过去时间(这表明他们应该当即开始迁移),也能是未来时间(一般这意味着他们要迁移到的新环境尚未准备就绪)。以下所示:
Deprecation: Thu, 21 Jan 2021 23:59:59 GMT

若是你要废弃整个端点或服务,那么你能够在每一个响应中都带上这样的头信息。若是你想要废弃的是一个具体的特性,多是一个参数、请求方法或者请求体中的某个特定字段的话,那么你应该在该特性被使用的时候才在响应中包含这个头信息。

为了给客户端更多的信息,咱们还可使用Link HTTP 响应头信息连接至端点或人类易读的文档。在同一个Link头信息中,咱们能够包含多个这样的连接,只须要使用逗号进行分割便可(后面咱们会看到一个完整的例子)。该规范定义了四个与 API 废弃相关的连接:

 Deprecation 连接咱们能够为 deprecation 连接指向一我的类易于阅读的描述:
Link: <https://developer.example.com/deprecation>; rel="deprecation"; type="text/html"

这是告诉用户发生了什么以及他们该怎么办的主要方式。你应该始终使用它。若是尚未完整的详情和最终的关闭日期,那么即便只是一个占位符,这也是颇有帮助的。在这种状况下,不要忘记让用户订阅更新,这能够采用邮件列表、RSS 或其余相似的方式来实现。

 Latest-Version 连接若是你但愿客户端转移至 API 相同端点的最新版本,那么可使用该连接指向它,以下所示:
Link: <https://api.example.com/v10/customers>; rel="latest-version"
 Latest-Version 连接若是你的 API 有多个可用的版本,一般最好每次向前迁移一个版本,而不是直接从最老的、现已废弃的版本跳到最新的版本。为了帮助解决这个问题,咱们连接至已废弃版本的下一个版本,而不是最新版本,以下所示:
Link: <https://api.example.com/v2/customers>; rel="successor-version"
 Successor-Version 连接若是该 API 没有新的等价版本,用户最好迁移到一个彻底不一样的资源,它多是一个很好的替代方案,那么咱们使用 alternate 连接来指明这一点,以下所示:
Link: <https://api.example.com/v2/users/123/clients>; rel="alternate"
Sunset 头信息

若是你知道了 API 什么时候彻底关闭的话,那么就应该添加一个 Sunset 头信息。

https://datatracker.ietf.org/doc/rfc8594/?include_text=1

Sunset 头信息告诉客户端 API 什么时候会中止运行。这是一个强制的截止时间:API 客户端必需要在这个日期前进行迁移,咱们承诺在这个时间前不会破坏任何事情。

在这里,咱们必需要提供一个时间,它应该是一个将来的时间。不过,若是它是一个过去的时间,这也是能够的:此时就至关于说“这个 API 会在任意时刻关闭,你须要当即中止使用它”。它以下所示:
Sunset: Tue, 20 Jul 2021 23:59:59 GMT

这很是简单,它不只能够用到 API 关闭的场景中:咱们能用它来标记未来 URL 迁移的 HTTP 重定向,或者代表特定 URL 有限的生命周期(适用于临时性的内容,或者适用于具备监管要求的特定资源,好比数据保留策略)。它所说明的就是“这个端点可能在该日期后不会再按照你的预期运行,请作好准备”。

 Sunset 连接该规范也提供了一个 Sunset 连接的关系。按照设计,它会连接相当于关闭特定端点更加详细的信息(若是你有 deprecation 连接的话,它们可能会是同一个)或者关于服务的通用 Sunset 策略。以下所示:
Link: <http://developer.example.com/our-sunset-policy>;rel="sunset";type="text/html"

在这里咱们也要指出,通用的 Sunset 策略是很是有用的!Sunset 策略会告诉客户端,当咱们关闭端点的时候(好比,一年后替代方案上线),用户该如何确保他们能得知这一状况(邮件列表、状态页面、HTTP 头信息等)以及他们一般应该作些什么(更新、检查文档、听从Link头信息)。

若是立刻就要废弃某个 API 的话,添加这样的连接做用其实不大,可是若是你能在一年前就将其发布出去的话,你的客户端可能已经为此作好了准备。

除此以外,发布 Sunset/Deprecation 策略的最好时间就是如今。若是你刚好正以某种方式编写 Deprecation 文档的话,这么作是值得考虑的。

组合到一块儿按照设计,这些组成部分能很好地协做。例如,为了代表某个最近废弃的 API,该 API 会在 6 个月内完全关闭,咱们要连接至文档并提供下一个版本的直接连接,那么咱们应该在响应中包含以下的头信息连接:
Deprecation: Thu, 21 Jan 2021 23:59:59 GMT
Sunset: Tue, 20 Jul 2021 23:59:59 GMT
Link: <https://api.example.com/v2/customers>; rel="successor-version",
    <https://developer.example.com/shutting-down-customers-v1>; rel="deprecation"
3. 渐进式关闭

若是全部这些都已经准备到位,而且 sunset 截止时间已过,那么咱们就能够将 API 关闭了。

可是,这并不意味着你须要当即且完全消灭该 API。渐进式关闭能有助于确保任何使用该 API 的全部客户端都有最后的机会在它完全消失前获得最后一次警告。GitHub 在 2018 年移除一些加密支持的时候曾经这样作:首先禁用一个小时,而后启用它,最后在两周后完全禁用了它。

https://github.blog/2018-02-01-crypto-removal-notice/

这里还有另一个技巧:安卓在 2015 年为已废弃的原生 API 增长了愈来愈多的延迟,在完全关闭 API 前,最终达到了 16 秒的等待。

https://twitter.com/jbaruch/status/930476565065953280

这些渐进式的关闭为那些错过截止日期的客户端提供了一些灵活性,而且能帮助那些没有注意到废弃时间点的客户端,从而能在 API 完全关闭以前处理一些问题。

4. 谨慎行事

无论采用哪一种方式,只要你尽了最大的努力去沟通关于 API 关闭的事情,那么如今就能够关闭端点 / 特性 / 整个服务,删除代码,而后睡个好觉。

像这样当心谨慎地进行废弃和关闭,可让你的客户端尽量清楚地知道他们该如何依赖你的 API,什么时候须要采起行动,以及他们须要作什么。这种变动多是一件大事儿,这些信息是很重要的。

这些新的草案头信息让咱们不只能够与人类沟通,还能将这些信息暴露给自动化系统。随着这些头信息的普及,我很高兴地开始看到有更多的工具创建在它们之上。通用的 HTTP 客户端能够根据这些数据自动记录有用的警告日志,API 生成器自己也能根据 API 规范处理愈来愈多的问题,而 HTTP 调试器(如 HTTP Toolkit)能够在截获的实时流量中为你突出显示废弃端点的使用。这是一个使人激动的时刻,咱们能够开始安全地关闭 API 了!

https://httptoolkit.tech/

须要注意的是,这些头信息是 HTTP 规范的草案。在最终肯定前,它们有可能会发生变化。也就是说,它们经历了几轮修改,从如今开始,它们不太可能发生巨大的变化,如今能普遍测试它们了。

不过这也意味着还有时间进行反馈! 若是你对它们的工做方式和如何更好地运行有想法的话,请与“Building Blocks for HTTP APIs”工做组联系。你能够给邮件列表发邮件:httpapi@ietf.org。

 延伸阅读

https://httptoolkit.tech/blog/how-to-turn-off-your-old-apis/

 

END

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

 

推荐阅读  点击标题可跳转

前端 API 请求缓存的5个方案

10个不为人知但很实用的Web API

一篇文章上手Vue3中新增的API

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=