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!
相关推荐
网络安全King1 小时前
【D04】网络安全基本命令
开发语言·网络·安全·web安全·php
蜗牛去旅行吧1 小时前
深入理解电子邮件安全:SPF、DKIM 和 DMARC 完全指南
服务器·网络·安全
Peter_chq1 小时前
【计算机网络】HTTPS协议
linux·c语言·开发语言·网络·c++·后端·网络协议
XMYX-02 小时前
HTTP/3 深入解读:现代互联网的加速引擎
网络·网络协议·http
黑客Ela2 小时前
常见的端口漏洞及常见网络安全设备默认口令
网络·安全·web安全
安全系统学习4 小时前
网络安全最新XSS漏洞
网络·安全·web安全·网络安全·xss
co0t4 小时前
计算机网络(12)介质访问控制
网络
WXDcsdn5 小时前
华为三层交换机禁止VLAN间通讯(两种解决方案)
运维·网络·华为
Fantasy丶夜雨笙歌5 小时前
【HCIP]——OSPF综合实验
网络·智能路由器