如何在Connexion/Flask/Werkzeug应用的请求中获取base_path
我刚好在维护多OpenAPI规范的Connexion项目时遇到过一模一样的需求,分享几个亲测有效的方法给你,都能准确获取当前请求对应的完整base_path:
方法1:通过Flask Request对象直接拼接(推荐)
Connexion底层基于Flask,所以可以直接用Flask原生的request对象来构建你需要的完整base_path。request包含了请求的所有上下文信息,能精准匹配当前请求对应的API版本:
from flask import request def get_pet(pet_id): pet = PETS.get(pet_id) # 拼接完整base_path:协议 + 域名端口 + API前缀 base_path = f"{request.scheme}://{request.host}{request.root_path}" print(base_path) # 输出示例: http://0.0.0.0:8080/v1.0 return pet or ('Not found', 404)
这里的request.root_path就是当前请求匹配的OpenAPI规范配置的base_path(比如/v1.0),结合scheme(http/https)和host(域名+端口),就能得到你需要的完整路径字符串。这个方法简单直接,兼容性强,不会受Connexion版本更新影响。
方法2:直接获取Connexion API实例的Base Path
如果你的应用通过add_api()加载了多个不同base_path的OpenAPI文件,可以直接从Connexion的上下文获取当前请求对应的API实例的base_path,再补全完整路径:
import connexion from flask import request def get_pet(pet_id): pet = PETS.get(pet_id) # 获取当前请求对应的API实例的base_path配置 api_base_path = connexion.current_app.api.base_path # 拼接完整路径 base_path = f"{request.scheme}://{request.host}{api_base_path}" print(base_path) return pet or ('Not found', 404)
当请求匹配到某个API规范时,connexion.current_app.api会指向对应的API实例,它的base_path属性就是你在加载API时配置的前缀,能完美区分不同版本的API。
方法3:全局注入Base Path(适合多视图复用)
如果需要在多个请求处理函数中使用base_path,可以用Flask的before_request钩子,把base_path存入请求上下文的g对象,这样所有视图函数都能直接取用,不用重复拼接:
import connexion from flask import request, g # 初始化Connexion应用并加载多个API规范 app = connexion.App(__name__) app.add_api('pet_v1.yaml', base_path='/v1.0') app.add_api('pet_v2.yaml', base_path='/v2.0') # 全局钩子:在每个请求处理前注入base_path @app.before_request def inject_base_path(): g.base_path = f"{request.scheme}://{request.host}{request.root_path}" def get_pet(pet_id): pet = PETS.get(pet_id) # 直接从g对象获取已注入的base_path print(g.base_path) return pet or ('Not found', 404)
这个方法一次性配置,所有视图函数都能直接用g.base_path,非常适合大型项目复用。
以上三种方法都能满足你区分不同base_path的需求,我个人最推荐方法1,因为它完全依赖Flask原生能力,稳定且易维护。
内容的提问来源于stack exchange,提问作者Rory Savage

