6.3 按环境管理文档入口
按环境管理文档入口
FastAPI 默认提供 Swagger UI、ReDoc 和 OpenAPI JSON。开发和测试环境通常需要这些入口来调试接口;面向公众的 API 可以根据产品需求开放文档,内部 API 则应结合网络边界、身份认证或网关策略决定是否开放。关键是把选择写进配置,而不是在不同模块里手工拼接 URL。
docs_url 控制 Swagger UI,redoc_url 控制 ReDoc,openapi_url 控制 OpenAPI JSON。两个文档界面都依赖 OpenAPI schema;将 openapi_url=None 会同时关闭使用它的文档界面。若只把 docs_url=None,ReDoc 或 OpenAPI JSON 仍可能可访问,因此关闭方案应明确设置三者的关系。
关闭文档入口不等于保护接口。下面的 /posts 在文档关闭后仍然返回 200,真实应用仍需用第四章的认证和权限依赖保护业务接口。隐藏 /docs 路径也不是访问控制,内部文档若要开放,应由反向代理、网络策略或认证机制提供额外保护。
用配置构造应用
本示例复用第三章的 pydantic-settings 思路:配置有明确类型,环境变量使用 APP_ 前缀,生产环境的决定通过部署配置传入。示例用 docs_enabled 显式控制文档开关,默认值适合本地开发;生产配置必须经过部署环境的明确选择,不能把默认值当作所有产品的安全方案。
<!-- file: ch06_environment/docs_environment_demo.py -->
from __future__ import annotations
from typing import Literal
from fastapi import FastAPI
from fastapi.testclient import TestClient
from pydantic_settings import BaseSettings, SettingsConfigDict
class AppSettings(BaseSettings):
model_config = SettingsConfigDict(
env_prefix="APP_",
extra="ignore",
)
environment: Literal["dev", "test", "prod"] = "dev"
docs_enabled: bool = True
docs_url: str = "/docs"
redoc_url: str | None = "/redoc"
openapi_url: str = "/openapi.json"
def create_app(settings: AppSettings) -> FastAPI:
if settings.docs_enabled:
docs_url = settings.docs_url
redoc_url = settings.redoc_url
openapi_url = settings.openapi_url
else:
# 三个入口一起关闭,避免留下可访问的 schema 或另一套 UI。
docs_url = None
redoc_url = None
openapi_url = None
app = FastAPI(
title="文章管理 API",
version="1.0.0",
docs_url=docs_url,
redoc_url=redoc_url,
openapi_url=openapi_url,
)
@app.get("/posts")
def list_posts() -> list[dict[str, str]]:
# 文档开关不改变业务路由;真实项目仍要在这里接入鉴权依赖。
return [{"id": "1", "title": "示例文章"}]
return app
def self_check() -> None:
development = create_app(
AppSettings(environment="dev", docs_enabled=True)
)
with TestClient(development) as client:
assert client.get("/docs").status_code == 200
assert client.get("/redoc").status_code == 200
assert client.get("/openapi.json").status_code == 200
assert client.get("/posts").status_code == 200
production = create_app(
AppSettings(environment="prod", docs_enabled=False)
)
with TestClient(production) as client:
assert client.get("/docs").status_code == 404
assert client.get("/redoc").status_code == 404
assert client.get("/openapi.json").status_code == 404
# 业务接口仍然存在;文档关闭不是业务鉴权。
assert client.get("/posts").status_code == 200
internal = create_app(
AppSettings(
environment="test",
docs_enabled=True,
docs_url="/internal/docs",
redoc_url=None,
openapi_url="/internal/openapi.json",
)
)
with TestClient(internal) as client:
assert client.get("/internal/docs").status_code == 200
assert client.get("/internal/openapi.json").status_code == 200
assert client.get("/redoc").status_code == 404
assert client.get("/openapi.json").status_code == 404
print("docs_environment_demo self-check passed")
if __name__ == "__main__":
self_check()
运行检查前安装本节新增的配置依赖:
python -m pip install "pydantic-settings"
然后运行:
python ch06_environment/docs_environment_demo.py
预期输出:
docs_environment_demo self-check passed
公共 API 和内部 API 的选择
公共 API 是否开放文档取决于调用方是否需要发现接口、产品是否愿意公开模型和错误信息,以及文档内容是否已经过版本管理。即使开放 /docs,也不能在示例数据、描述或 OpenAPI 扩展中放入密钥、内部地址和调试信息。
内部 API 可以在开发、测试环境开放完整文档,在生产环境关闭入口;如果生产运维需要文档,可以像示例的 internal 配置一样使用独立路径,并在网关层要求身份和网络条件。把路径改成 /internal/docs 只改善路由组织,不会自动增加认证。
openapi_url 是 schema 的来源。Swagger UI 和 ReDoc 会从它读取接口定义;因此设置自定义路径时,三者应一起检查。只关闭 ReDoc 不会关闭 Swagger,也不会关闭 OpenAPI JSON;只关闭 Swagger 也同理。关闭 OpenAPI schema 时,FastAPI 会让依赖它的两个 UI 不可用。
配置验证和部署边界
AppSettings 的 docs_enabled 是布尔字段,环境变量 APP_DOCS_ENABLED=false 会被 pydantic-settings 解析为 False。生产部署应在启动检查中明确打印“文档已关闭/开放”的非敏感状态,或在配置审查中验证它;不要通过请求 /docs 判断所有安全策略已经生效。
文档开关只负责入口配置,不负责认证、授权、限流或数据脱敏。业务接口仍需要安全依赖、响应模型和错误处理;OpenAPI 关闭后,接口本身不会自动变得更安全,也不会改变已有客户端请求的执行结果。
资料来源
- 主要参考:fastapi-best-practices 中文 README 的“文档”部分。本节保留按环境控制文档入口的主题,并把配置、三类 URL 和业务鉴权边界写成可运行示例。
- 官方文档:FastAPI 元数据和文档 URL、条件 OpenAPI。官方说明
docs_url、redoc_url和openapi_url的关系,以及将openapi_url设为None的效果。

免费 AI IDE


更多建议: