当前位置: 首页 > 知识库问答 >
问题:

如何在FastAPI中捕获一条路由上的任意路径?

况明贤
2023-03-14

我通过安装从FastAPI提供React应用程序

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

@app.route('/session')
async def renderReactApp(request: Request):
    return templates.TemplateResponse("index.html", {"request": request})

通过这个 React 应用程序得到服务,React 路由在客户端也能正常工作,但是一旦客户端重新加载未在服务器上定义但在 React 应用程序中使用的路由 FastAPI 返回找不到来解决此问题,我做了如下操作。

    < Li > < code > @ app . route('/network ') < Li > < code > @ app . route('/gat ') < Li > < code > @ app . route('/session ')
async def renderReactApp(request: Request):
    return templates.TemplateResponse("index.html", {"request": request})

但这对我来说似乎很奇怪,而且是错误的,因为我需要在后端和前端添加每条路由。

我肯定肯定有类似Flask@Flask_app.add_url_rule('/


共有3个答案

阎宝
2023-03-14

正如@mecampbellsoup指出的那样:通常还有其他静态文件需要与这样的应用程序一起提供。

希望这对其他人有用:

import os
from typing import Tuple

from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles

app = FastAPI()


class SinglePageApplication(StaticFiles):
    """Acts similar to the bripkens/connect-history-api-fallback
    NPM package."""

    def __init__(self, directory: os.PathLike, index='index.html') -> None:
        self.index = index

        # set html=True to resolve the index even when no
        # the base path is passed in
        super().__init__(directory=directory, packages=None, html=True, check_dir=True)

    async def lookup_path(self, path: str) -> Tuple[str, os.stat_result]:
        """Returns the index file when no match is found.

        Args:
            path (str): Resource path.

        Returns:
            [tuple[str, os.stat_result]]: Always retuens a full path and stat result.
        """
        full_path, stat_result = await super().lookup_path(path)

        # if a file cannot be found
        if stat_result is None:
            return await super().lookup_path(self.index)

        return (full_path, stat_result)



app.mount(
    path='/',
    app=SinglePageApplication(directory='path/to/dist'),
    name='SPA'
)

这些修改使得StaticFiles挂载行为类似于connect-history-API-fallback NPM包。

陆运乾
2023-03-14

我做了一个非常简单的函数,它完全兼容< code>react-router和< code>create-react-app应用程序(大多数用例)

from pathlib import Path
from typing import Union

from fastapi import FastAPI, Request
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates


def serve_react_app(app: FastAPI, build_dir: Union[Path, str]) -> FastAPI:
    """Serves a React application in the root directory `/`

    Args:
        app: FastAPI application instance
        build_dir: React build directory (generated by `yarn build` or
            `npm run build`)

    Returns:
        FastAPI: instance with the react application added
    """
    if isinstance(build_dir, str):
        build_dir = Path(build_dir)

    app.mount(
        "/static/",
        StaticFiles(directory=build_dir / "static"),
        name="React App static files",
    )
    templates = Jinja2Templates(directory=build_dir.as_posix())

    @app.get("/{full_path:path}")
    async def serve_react_app(request: Request, full_path: str):
        """Serve the react app
        `full_path` variable is necessary to serve each possible endpoint with
        `index.html` file in order to be compatible with `react-router-dom
        """
        return templates.TemplateResponse("index.html", {"request": request})

    return app
import uvicorn
from fastapi import FastAPI


app = FastAPI()

path_to_react_app_build_dir = "./frontend/build"
app = serve_react_app(app, path_to_react_app_build_dir)

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8001)
牟焱
2023-03-14
匿名用户

因为FastAPI是基于Starlette的,所以您可以在路由参数中使用他们所谓的“转换器”,在本例中使用type path,它“返回路径的其余部分,包括任何附加的< code>/字符。”

请参阅 https://www.starlette.io/routing/#path-parameters 以供参考。

如果你的 react (或 vue 或 ...) 应用程序使用的是基本路径,你可以做这样的事情,它将 /my-app/ 之后的任何内容分配给 rest_of_path 变量:

@app.get("/my-app/{rest_of_path:path}")
async def serve_my_app(request: Request, rest_of_path: str):
    print("rest_of_path: "+rest_of_path)
    return templates.TemplateResponse("index.html", {"request": request})

如果您没有使用/my-app/之类的唯一基本路径(这似乎是您的用例),您仍然可以使用包罗万象的路由来完成此操作,该路由应该跟踪任何其他路由,以便不会覆盖它们:

@app.route("/{full_path:path}")
async def catch_all(request: Request, full_path: str):
    print("full_path: "+full_path)
    return templates.TemplateResponse("index.html", {"request": request})

(事实上,为了捕捉对/my-app//my-app的请求之间的差异,您可能需要使用此catch all)

 类似资料:
  • 问题内容: 我有一个简单的Flask路由,我想捕获文件的路径。如果我在规则中使用它,则适用于,但无效。如何捕获任意路径,以便将其传递给视图函数? 问题答案: 使用path转换器捕获任意长度的路径:将捕获路径并将其传递给参数。默认转换器捕获单个字符串,但以斜杠停止,这就是为什么第一个URL匹配而第二个URL不匹配的原因。 如果你还想匹配根目录(斜杠和空路径),则可以添加另一个规则,该规则为path参

  • 我已经使用FastAPI创建了一个简单的API,我正在尝试将URL作为任意的<code>路径</code>参数传递给FastAPI路由。 当我测试它时,它不起作用并抛出错误。我以这种方式测试它:

  • 我正在开发一个Android应用程序。它有一个功能,捕获的图像应该显示在屏幕上,我需要得到那个图像路径,这样我就可以把那个图像发送到服务器。 我可以在屏幕上显示图像,但无法获得绝对图像路径。 我得到的路径像: 如何获取实际图像路径? 这是我的密码: 值如上所示。 我如何从这个路径得到我的绝对图像路径。