我通过安装从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 返回找不到
来解决此问题,我做了如下操作。
async def renderReactApp(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
但这对我来说似乎很奇怪,而且是错误的,因为我需要在后端和前端添加每条路由。
我肯定肯定有类似Flask@Flask_app.add_url_rule('/
正如@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包。
我做了一个非常简单的函数,它完全兼容< 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)
因为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应用程序。它有一个功能,捕获的图像应该显示在屏幕上,我需要得到那个图像路径,这样我就可以把那个图像发送到服务器。 我可以在屏幕上显示图像,但无法获得绝对图像路径。 我得到的路径像: 如何获取实际图像路径? 这是我的密码: 值如上所示。 我如何从这个路径得到我的绝对图像路径。