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!
相关推荐
诡异森林。20 分钟前
Docker--Docker网络原理
网络·docker·容器
ALex_zry34 分钟前
Docker Macvlan网络配置实战:解决“network already exists“错误
网络·docker·php
半路_出家ren39 分钟前
流量抓取工具(wireshark)
网络·网络协议·测试工具·网络安全·wireshark·流量抓取工具
layman05281 小时前
node.js 实战——(Http 知识点学习)
http·node.js
Gazer_S2 小时前
【HTTP/2:信息高速公路的革命】
网络·网络协议·http
lLinkl2 小时前
项目笔记2:post请求是什么,还有什么请求
服务器·网络协议·http
李匠20242 小时前
C++ RPC以及cmake
网络·c++·网络协议·rpc
科技小E3 小时前
EasyRTC音视频实时通话嵌入式SDK,打造社交娱乐低延迟实时互动的新体验
大数据·网络
静听夜半雨4 小时前
CANoe入门——3、新建LIN工程及LIN DataBase(LDF文件)的创建
网络·数据库·c++·编辑器
Jackilina_Stone4 小时前
【网工第6版】第5章 网络互联⑧
网络·软考·网工·第5章 网络互联