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!
相关推荐
昔时扬尘处8 小时前
【C2000系列DSP的不掉电升级】C2000 不掉电升级(LFU)方案详解(含流程、代码与官方方案适配)
网络·dsp·c2000·德州仪器·实时控制mcu·lfu不掉电升级·后台升级
ZHHHHHJ669 小时前
LL层-PAST
运维·服务器·网络
老蒋新思维9 小时前
创客匠人启示:破解知识交付的“认知摩擦”——IP、AI与数据的三角解耦模型
大数据·人工智能·网络协议·tcp/ip·重构·创客匠人·知识变现
百***07459 小时前
GPT-5.2 极速接入指南:流程详解与主流模型对比
网络·人工智能·gpt
REDcker10 小时前
TCP/IP 协议栈详解:协议栈是什么意思?为什么叫“协议栈”?
网络·网络协议·tcp/ip
老蒋新思维11 小时前
反脆弱性设计:创始人IP与AI智能体如何构建愈动荡愈强大的知识商业|创客匠人
人工智能·网络协议·tcp/ip·算法·机器学习·创始人ip·创客匠人
凯子坚持 c11 小时前
Docker网络架构深度解析:从原理到实战
网络·docker·架构
工控小楠11 小时前
Profinet从站转EtherNet IP主站协议网关应用于自动化生产线
网络协议·tcp/ip·自动化
cdprinter11 小时前
信刻光盘数据自动回读系统,多重保障数据安全及调阅便捷性!
网络·安全·自动化
发光小北12 小时前
SG-CAN (FD) NET-210(双通道 CAN (FD) 转以太网网关)特点与功能介绍
开发语言·网络·php