如何在CherryPy中为API添加版本控制解决路径报错问题
CherryPy 13.1.0 API版本控制实现方案
@cherrypy.expose的alias参数不支持包含斜杠的多级路径,仅能匹配当前路由层级下的单段路径别名,直接传入"v1/apiName"无法被路由表正确注册,请求时自然抛出路径不存在错误。
以下三种方案均基于CherryPy 13.1.0原生能力实现,无额外第三方依赖,性能损耗极低,适配CherryPy优于FastAPI的性能表现场景。
方案1:嵌套类映射版本前缀(推荐,零额外性能开销)
这是CherryPy树状路由设计的标准用法,直接将不同版本的API实现挂载到根路由对应版本的路径节点下,路由匹配走原生遍历逻辑,和单层级接口性能完全一致。
不同版本的逻辑可以通过类继承复用,仅需重写版本迭代中变更的接口即可,维护成本低。
import cherrypy # V1版本API集合 class V1API: @cherrypy.expose @cherrypy.tools.json_in() @cherrypy.tools.json_out() def apiName(self): # 原有业务逻辑 return {"version": "v1", "data": "success"} # 后续迭代V2版本时新增对应类即可 class V2API: @cherrypy.expose @cherrypy.tools.json_in() @cherrypy.tools.json_out() def apiName(self): # V2版本新逻辑 return {"version": "v2", "data": "success"} class Root: # 将版本类挂载到对应路径节点 v1 = V1API() v2 = V2API() if __name__ == "__main__": cherrypy.quickstart(Root())
启动后可直接通过/v1/apiName、/v2/apiName访问对应版本接口。
方案2:内置调度器自定义路由规则(适合不改动现有类结构的场景)
如果不想调整现有API类的代码结构,可以使用CherryPy内置的RoutesDispatcher自定义路径映射规则,直接将带版本前缀的路径绑定到对应处理方法。该方案仅多一层路由规则匹配,性能损耗可以忽略。
import cherrypy from cherrypy._cpdispatch import RoutesDispatcher # 原有API类无需调整结构 class APIClass: @cherrypy.expose @cherrypy.tools.json_in() @cherrypy.tools.json_out() def does_stuff(self): # 原有业务逻辑 return {"result": "process success"} if __name__ == "__main__": dispatcher = RoutesDispatcher() # 绑定v1版本路径到处理方法 dispatcher.connect("v1_does_stuff", "v1/apiName", controller=APIClass(), action="does_stuff") # 后续新增版本直接追加路由规则即可 server_config = { "/": {"request.dispatch": dispatcher} } cherrypy.quickstart(APIClass(), "/", server_config)
方案3:路径节点内部转发(适合临时快速兼容场景)
如果需要最小改动兼容现有写法,可以手动暴露版本号对应的路径节点,在节点内部做请求转发,该方案无额外网络开销,但是版本多了之后维护成本较高,适合小规模接口临时使用。
import cherrypy class APIClass: @cherrypy.expose(alias="apiName") @cherrypy.tools.json_in() @cherrypy.tools.json_out() def does_stuff(self): return {"result": "process success"} # 暴露v1路径节点 @cherrypy.expose def v1(self, *path_segs, **params): if path_segs and path_segs[0] == "apiName": return self.does_stuff() raise cherrypy.NotFound() if __name__ == "__main__": cherrypy.quickstart(APIClass())
内容的提问来源于stack exchange,提问作者baggy696
相关产品推荐
相关产品推荐

