这两天写了一个 Flask项目,项目中需要使用到 API Docs,找了很多都是需要嵌入到代码中的,这种会让代码变得很乱。最后还是打算延续之前的 yaml 的方式,还有就是 Flask 支持这种 Yaml 的配置,它有一个库 flask_swagger_ui。具体的代码就几行:
from flask import Flask, send_from_directory
from flask_swagger_ui import get_swaggerui_blueprint
app = Flask(__name__)
swaggerui_blueprint = get_swaggerui_blueprint(
"/api/docs", # Flask 内部的 URL 前缀
"./openapi.yaml",
config={"app_name": "Agent Management"},
)
# 把 openapi.yaml 静态文件挂载到 /api/docs/openapi.yaml
@swaggerui_blueprint.route("/openapi.yaml")
def openapi_yaml():
return send_from_directory("docs", "openapi.yaml")
app.register_blueprint(swaggerui_blueprint, url_prefix="/api/docs")
问题
这种方式在本地能够正常打开这个 API Docs,但是部署到 K8s中却出现了问题。这主要就是因为访问 Flask_swagger_ui 时会重定向请求。
比如:在访问 k8s 部署应用的外部地址 https://api-test-exmaple.com.cn/api/docs时,会重定向该请求,而重定向的 BaseUrl 却是 K8s的内部地址 https://api-test-exmaple.internal/api/docs。内部地址是集群内部访问的,所以就会请求失败
解决
为了解决这个问题,就需要在进行 flask_swagger_ui 配置时,正确的配置一个外部的 url,具体的修改如下:
from flask import Flask, send_from_directory
from flask_swagger_ui import get_swaggerui_blueprint
app = Flask(__name__)
EXTERNAL_SWAGGER_URL = "https://api-test-exmaple.com.cn/api/docs"
EXTERNAL_OPENAPI_YAML_URL = f"{EXTERNAL_SWAGGER_URL}/openapi.yaml"
swaggerui_blueprint = get_swaggerui_blueprint(
"/api/docs", # Flask 内部的 URL 前缀
EXTERNAL_OPENAPI_YAML_URL, # 告诉 Swagger UI 使用这个完整外部 URL 加载 openapi.yaml
config={"app_name": "Agent Management"},
)
# 把 openapi.yaml 静态文件挂载到 /api/docs/openapi.yaml
@swaggerui_blueprint.route("/openapi.yaml")
def openapi_yaml():
return send_from_directory("docs", "openapi.yaml")
app.register_blueprint(swaggerui_blueprint, url_prefix="/api/docs")
这样在重定向时,返回给浏览器的就是外部地址了,就能正确的打开 swagger了
总结
之前在写 swagger文档时,会把整个 swagger-ui放到路由下面,包括那些 css,js文件。而这次只有一个 yaml文档,其他的文档都是通过 flask_swagger_ui 访问,所以就出现了这个问题