HTTP 响应头 Deprecation 字段在 API 版本迭代的应用

API 版本迭代过程中,我们希望使用者能保持使用新版本 API,并且知道他正在使用的旧版本 API 即将废弃。维护者与使用者关于这点的沟通通常通过下面的方式:

  1. 维护者定期更新网站中 API 版本信息,使用者定期关注
  2. 维护者通过邮件主动通知使用者

这两种方式并不可靠,如果双方开发人员可以在程序交互时就交流这个信息,会比依赖人的通知更为准时可靠。

目前社区打算引进一个新的 HTTP 响应头字段 Deprecation 来传递这个信息

字段的格式:Deprecation: 1688169599

应用案例

原始版本

下面的案例中存在两个版本,使用者使用的是旧版本的接口,版本的信息交互只能通过响应体中的 [Version 1] 来传递(实际应用中可能在 json 响应字段中或者其他地方),这种方式的问题在于它不具备普适性,每个外部依赖的 API 关于版本废弃的信息格式和位置都不一样,很难做基础开发。

python 复制代码
from flask import Flask

app = Flask(__name__)

@app.route("/v1/list_books")
def get_book_list():
    return "This is a book list! [Version 1]"

@app.route("/v2/list_books")
def get_book_list_v2():
    return "This is a book list! [Version 2]"
shell 复制代码
➜  ~ curl -i http://172.21.208.1:5000/v1/list_books
HTTP/1.1 200 OK
Server: Werkzeug/3.0.6 Python/3.11.9
Date: Mon, 18 Nov 2024 07:04:25 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 20
Connection: close

This is a book list!%

使用 Deprecated 字段版本

python 复制代码
from datetime import datetime

from flask import Flask, make_response

app = Flask(__name__)

@app.route("/v1/list_books")
def get_book_list():
    resp = make_response("This is a book list!")
    deprecation_date = int(datetime(2024,11,20,23,59,59).timestamp())
    resp.headers["Deprecation"] = deprecation_date
    return resp

@app.route("/v2/list_books")
def get_book_list_v2():
    return "This is a book list! [Vesion 2]"
复制代码
➜  ~ curl -i http://172.21.208.1:5000/v1/list_books
HTTP/1.1 200 OK
Server: Werkzeug/3.0.6 Python/3.11.9
Date: Mon, 18 Nov 2024 08:36:03 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 20
Deprecation: 1732118399
Connection: close

这个版本只是增加了一个头字段,但对于API使用者来说可以做的发挥就增加了。

由于字段与时间表示方式遵循协议制定的格式,使用者可以做统一的开发,在响应头提取到 Deprecation 字段后:

  1. 使用者的系统对外部调用的API 统一监测响应头中的 Deprecation 字段,发出提示和告警,对于已经到达时间阈值内的发出告警
  2. 项目的请求中间件可以据此发出警告日志,从而使得在开发时得到提醒

下面我对这种应用做下基本演示:

python 复制代码
# 客户端代码
import logging
import time
from datetime import timedelta

import requests

logger = logging.Logger("Detect")


def api_response_hook(func):
    def new_func():
        resp = func()
        deprecation = resp.headers.get("Deprecation")
        if deprecation:
        	# 对 deprecation 提取到的时间值做计算,开发者可以清楚感知到还剩几天过期
            seconds = int(deprecation) - int(time.time())
            remain_days = timedelta(seconds=seconds).days
            logger.warning(f"Warning:{resp.request.url} will be deprecate after {remain_days} days!")
        return resp

    return new_func

@api_response_hook
def list_books():
    resp = requests.get("http://127.0.0.1:5000/v1/list_books")
    return resp

def main():
    resp = list_books()
    print(resp.text)


if __name__ == "__main__":
    main()
复制代码
Warning:http://127.0.0.1:5000/v1/list_books will be deprecate after 2 days!
This is a book list!
相关推荐
橘颂TA24 分钟前
【Linux 网络】深入理解 UDP
linux·运维·服务器·网络·网络协议
yuanmenghao10 小时前
车载Linux 系统问题定位方法论与实战系列 - 车载 Linux 平台问题定位规范
linux·运维·服务器·网络·c++
上海云盾安全满满12 小时前
高防IP线路质量重要吗
网络·网络协议·tcp/ip
hoududubaba13 小时前
ORAN共享小区的基本概念
网络·网络协议
山峰哥13 小时前
数据库工程核心:SQL调优让查询效率飙升的实战密码
网络·汇编·数据库·sql·编辑器
梁辰兴16 小时前
计算机网络基础:网络地址转换
网络·计算机网络·计算机·nat·计算机网络基础·梁辰兴·网络地址转换协议
Q168496451516 小时前
红帽Linux-进程、ssh、网络、软件包、文件系统
linux·运维·网络
tobias.b17 小时前
408真题解析-2009-39-网络-TCP拥塞控制
网络·网络协议·tcp/ip·计算机考研·408考研·408真题解析
数通工程师17 小时前
IPv4和IPv6 地址分配:从划分到工具全解析
网络·网络协议·tcp/ip·华为
小白电脑技术18 小时前
玩客云OneCloud插入内存卡之后,开机自动挂载教程
网络·电脑