python fastapi swagger 连接超时

问题描述

运行python项目时,访问fastapi swagger出现连接超时。

https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui.css

https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui-bundle.js

解决方案

第一步 下载文件

https://pan.baidu.com/s/1EfKqxJvHKKs3vZEjTsYlIw

提取码: 1024

或者从github地址获取

https://github.com/swagger-api/swagger-ui
https://github.com/Redocly/redoc

文件下载后保存在目录 static/swagger-ui 中(与app.py)同级。

第二步 修改docs.py

我使用的是miniconda

C:\Users\Jack\.conda\envs\python_project\Lib\site-packages\fastapi\openapi\docs.py

Jack 为计算机用户名,python_projct 为conda虚拟环境

swagger_js_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui-bundle.js",
swagger_css_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui.css",
swagger_favicon_url: str = "https://fastapi.tiangolo.com/img/favicon.png",

更新如下

    swagger_js_url: str = "/static/swagger-ui/swagger-ui-bundle.js",
    swagger_css_url: str = "/static/swagger-ui/swagger-ui.css",
    swagger_favicon_url: str = "/static/swagger-ui/favicon-32x32.png",

注释以下代码

redoc_js_url: str = "https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js",
redoc_favicon_url: str = "https://fastapi.tiangolo.com/img/favicon.png",

更新如下

    redoc_js_url: str = "/static/redoc/bundles/redoc.standalone.js",
    redoc_favicon_url: str = "/static/redoc/favicon.png",

第三步 修改app.py

from starlette.staticfiles import StaticFiles  # 先引用包
from fastapi import FastAPI
import uvicorn

app = FastAPI(
    title=settings.APP_NAME,
    description=settings.APP_DESCRIPTION,
    version=settings.APP_VERSION,
    docs_url=settings.APP_DOCS_URL
)

app.mount('/static', StaticFiles(directory='static'), name='static')

if __name__ == "__main__":
    setup_database()
    uvicorn.run("app:app", host=settings.RUN_HOST, port=settings.RUN_PORT, reload=True)

运行项目后访问 http://localhost:8002/docs

附录

docs.py

import json
from typing import Any, Dict, Optional

from fastapi.encoders import jsonable_encoder
from starlette.responses import HTMLResponse

swagger_ui_default_parameters = {
    "dom_id": "#swagger-ui",
    "layout": "BaseLayout",
    "deepLinking": True,
    "showExtensions": True,
    "showCommonExtensions": True,
}


def get_swagger_ui_html(
    *,
    openapi_url: str,
    title: str,
    #swagger_js_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui-bundle.js",
    #swagger_css_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui.css",
    #swagger_favicon_url: str = "https://fastapi.tiangolo.com/img/favicon.png",
    
    swagger_js_url: str = "/static/swagger-ui/swagger-ui-bundle.js",
    swagger_css_url: str = "/static/swagger-ui/swagger-ui.css",
    swagger_favicon_url: str = "/static/swagger-ui/favicon-32x32.png",
    oauth2_redirect_url: Optional[str] = None,
    init_oauth: Optional[Dict[str, Any]] = None,
    swagger_ui_parameters: Optional[Dict[str, Any]] = None,
) -> HTMLResponse:
    current_swagger_ui_parameters = swagger_ui_default_parameters.copy()
    if swagger_ui_parameters:
        current_swagger_ui_parameters.update(swagger_ui_parameters)

    html = f"""
    <!DOCTYPE html>
    <html>
    <head>
    <link type="text/css" rel="stylesheet" href="{swagger_css_url}">
    <link rel="shortcut icon" href="{swagger_favicon_url}">
    <title>{title}</title>
    </head>
    <body>
    <div id="swagger-ui">
    </div>
    <script src="{swagger_js_url}"></script>
    <!-- `SwaggerUIBundle` is now available on the page -->
    <script>
    const ui = SwaggerUIBundle({{
        url: '{openapi_url}',
    """

    for key, value in current_swagger_ui_parameters.items():
        html += f"{json.dumps(key)}: {json.dumps(jsonable_encoder(value))},\n"

    if oauth2_redirect_url:
        html += f"oauth2RedirectUrl: window.location.origin + '{oauth2_redirect_url}',"

    html += """
    presets: [
        SwaggerUIBundle.presets.apis,
        SwaggerUIBundle.SwaggerUIStandalonePreset
        ],
    })"""

    if init_oauth:
        html += f"""
        ui.initOAuth({json.dumps(jsonable_encoder(init_oauth))})
        """

    html += """
    </script>
    </body>
    </html>
    """
    return HTMLResponse(html)


def get_redoc_html(
    *,
    openapi_url: str,
    title: str,
    #redoc_js_url: str = "https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js",
    #redoc_favicon_url: str = "https://fastapi.tiangolo.com/img/favicon.png",
    redoc_js_url: str = "/static/redoc/bundles/redoc.standalone.js",
    redoc_favicon_url: str = "/static/redoc/favicon.png",
    with_google_fonts: bool = True,
) -> HTMLResponse:
    html = f"""
    <!DOCTYPE html>
    <html>
    <head>
    <title>{title}</title>
    <!-- needed for adaptive design -->
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    """
    if with_google_fonts:
        html += """
    <link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
    """
    html += f"""
    <link rel="shortcut icon" href="{redoc_favicon_url}">
    <!--
    ReDoc doesn't change outer page styles
    -->
    <style>
      body {{
        margin: 0;
        padding: 0;
      }}
    </style>
    </head>
    <body>
    <redoc spec-url="{openapi_url}"></redoc>
    <script src="{redoc_js_url}"> </script>
    </body>
    </html>
    """
    return HTMLResponse(html)


def get_swagger_ui_oauth2_redirect_html() -> HTMLResponse:
    html = """
    <!DOCTYPE html>
    <html lang="en-US">
    <body onload="run()">
    </body>
    </html>
    <script>
        'use strict';
        function run () {
            var oauth2 = window.opener.swaggerUIRedirectOauth2;
            var sentState = oauth2.state;
            var redirectUrl = oauth2.redirectUrl;
            var isValid, qp, arr;

            if (/code|token|error/.test(window.location.hash)) {
                qp = window.location.hash.substring(1);
            } else {
                qp = location.search.substring(1);
            }

            arr = qp.split("&")
            arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';})
            qp = qp ? JSON.parse('{' + arr.join() + '}',
                    function (key, value) {
                        return key === "" ? value : decodeURIComponent(value)
                    }
            ) : {}

            isValid = qp.state === sentState

            if ((
            oauth2.auth.schema.get("flow") === "accessCode"||
            oauth2.auth.schema.get("flow") === "authorizationCode"
            ) && !oauth2.auth.code) {
                if (!isValid) {
                    oauth2.errCb({
                        authId: oauth2.auth.name,
                        source: "auth",
                        level: "warning",
                        message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"
                    });
                }

                if (qp.code) {
                    delete oauth2.state;
                    oauth2.auth.code = qp.code;
                    oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
                } else {
                    let oauthErrorMsg
                    if (qp.error) {
                        oauthErrorMsg = "["+qp.error+"]: " +
                            (qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
                            (qp.error_uri ? "More info: "+qp.error_uri : "");
                    }

                    oauth2.errCb({
                        authId: oauth2.auth.name,
                        source: "auth",
                        level: "error",
                        message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server"
                    });
                }
            } else {
                oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
            }
            window.close();
        }
    </script>
        """
    return HTMLResponse(content=html)

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
FastAPI 是一个现代化的 Web 框架,它基于 Python 3.6+,并使用了一些最新的技术,如 type hints、asyncio 和 Pydantic。FastAPI 可以让你快速地构建高性能的 Web 应用程序和 API。 Swagger 是一种 API 文档和交互式测试工具,它可以帮助开发者快速地了解和测试 API。FastAPI 集成了 Swagger UI,使开发者可以通过浏览器轻松地查看和测试 API。 在 FastAPI 中,只需要使用少量的代码就可以生成 Swagger 文档。你可以使用 FastAPI 内置的 `FastAPIOpenAPI` 和 `FastAPISwaggerUI` 类来集成 Swagger UI,代码示例如下: ```python from fastapi import FastAPI from fastapi.openapi.utils import get_openapi from fastapi.responses import HTMLResponse from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates from fastapi import FastAPI from fastapi.openapi.utils import get_openapi from fastapi.responses import JSONResponse, HTMLResponse from fastapi import FastAPI from fastapi.openapi.utils import get_openapi from fastapi.responses import JSONResponse, HTMLResponse from fastapi import FastAPI from fastapi.openapi.utils import get_openapi from fastapi.responses import JSONResponse, HTMLResponse from fastapi import FastAPI from fastapi.openapi.utils import get_openapi from fastapi.responses import JSONResponse, HTMLResponse app = FastAPI() # 静态文件 app.mount("/static", StaticFiles(directory="static"), name="static") # 模板文件 templates = Jinja2Templates(directory="templates") # 路由 @app.get("/", response_class=HTMLResponse) async def home(request: Request): return templates.TemplateResponse("index.html", {"request": request, "title": "FastAPI"}) @app.get("/docs", response_class=HTMLResponse) async def read_docs(request: Request): return templates.TemplateResponse("docs.html", {"request": request, "title": "API 文档"}) @app.get("/openapi.json", response_class=JSONResponse) async def get_open_api_endpoint(): return JSONResponse(get_openapi(title="FastAPI", version="0.1.0", app=app)) # 启动 FastAPI if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8000) ``` 在上面的代码中,我们创建了一个 `FastAPI` 实例,并使用 `app.mount` 方法来加载静态文件。然后,我们使用 `Jinja2Templates` 类来加载模板文件。接下来,我们定义了三个路由:`/`、`/docs` 和 `/openapi.json`。其中,`/` 和 `/docs` 路由返回 HTML 页面,`/openapi.json` 路由返回 Swagger 文档。 最后,我们使用 `uvicorn` 模块来启动 FastAPI。启动后,我们可以通过浏览器访问 `http://localhost:8000/docs` 来查看 Swagger UI。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值