fastapi: docs中执行到接口的访问时,配置请求前缀

一,配置:

下面的配置针对的是:父子应用,当前子应用前缀/api, 而且重写了docs的显示:

# 创建FastAPI应用,并传入 lifespan
api_app = FastAPI(title="我的API项目",
                  # docs_url=None,
                  docs_url=None,
                  redoc_url=None,
                  openapi_url=None,
                  root_path="/api",
                  )

if IS_DEV:
    security = HTTPBasic(realm="ApiPortal")

    # 2. 账号密码校验函数
    def datetime_verify_docs(credentials: HTTPBasicCredentials = Depends(security)):
        # 使用 secrets.compare_digest 防范计时攻击 (Timing Attacks)
        correct_username = secrets.compare_digest(credentials.username, "api_user")
        correct_password = secrets.compare_digest(credentials.password, "123456")

        if not (correct_username and correct_password):
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="用户名或密码错误",
                headers={"WWW-Authenticate": 'Basic realm="ApiPortal"'},
            )
        return credentials.username


    # 3. 手动重写 /openapi.json 并加锁
    @api_app.get("/openapi.json", include_in_schema=False)
    async def get_open_api_endpoint(request: Request,username: str = Depends(datetime_verify_docs)):
        if IS_DEV:
            # 动态获取当前的 root_path (即 "/api")
            root_path = request.scope.get("root_path", "")
            # 显式构造 servers 参数
            servers = [{"url": root_path}] if root_path else [{"url": "/"}]
            # 手动触发 get_openapi,并把包含前缀的 servers 传进去
            openapi_schema = get_openapi(
                title=api_app.title,
                version=api_app.version,
                routes=api_app.routes,
                servers=servers  # <-- 关键:告诉 Swagger UI 调试时必须加这个前缀!
            )
            return openapi_schema
        else:
            return None


    # 4. 手动重写 /docs 并加锁
    @api_app.get("/docs", include_in_schema=False)
    async def get_documentation(request: Request, username: str = Depends(datetime_verify_docs)):
        root_path = request.scope.get("root_path", "").rstrip("/")
        return get_swagger_ui_html(openapi_url=f"{root_path}/openapi.json",
                                   title=api_app.title + " - Docs",
                                   # 【核心修正 3】:静态资源路径也必须拼接 root_path,否则会去根目录下找,导致404或找错
                                   swagger_js_url=f"/static/swagger/swagger-ui-bundle.js",
                                   swagger_css_url=f"/static/swagger/swagger-ui.css",
                                   swagger_favicon_url=f"/static/swagger/favicon.png"
                                   )

 

二,测试效果:

未添加前缀前:

image

添加前缀后:

image

posted @ 2026-07-26 16:39  刘宏缔的架构森林  阅读(10)  评论(0)    收藏  举报