Last active
November 21, 2024 17:37
-
-
Save ultrafunkamsterdam/b1655b3f04893447c3802453e05ecb5e to your computer and use it in GitHub Desktop.
FastAPI support for React ( with working react-router )
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
███████╗ █████╗ ███████╗████████╗ █████╗ ██████╗ ██╗ | |
██╔════╝██╔══██╗██╔════╝╚══██╔══╝██╔══██╗██╔══██╗██║ | |
█████╗ ███████║███████╗ ██║ ███████║██████╔╝██║ | |
██╔══╝ ██╔══██║╚════██║ ██║ ██╔══██║██╔═══╝ ██║ | |
██║ ██║ ██║███████║ ██║ ██║ ██║██║ ██║ | |
╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ | |
██████╗ ███████╗ █████╗ ██████╗████████╗ | |
██╔══██╗ ██╔════╝ ██╔══██╗ ██╔════╝╚══██╔══╝ | |
██████╔╝ █████╗ ███████║ ██║ ██║ | |
██╔══██╗ ██╔══╝ ██╔══██║ ██║ ██║ | |
██║ ██║ ███████╗ ██║ ██║ ╚██████╗ ██║ | |
╚═╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ | |
serve react app via fastapi, complete with working react-router | |
How to use ? | |
------- | |
it's actually very simple. | |
create your fastapi app like you'd normally do | |
but you have to use this as your VERY LAST mount to your main app | |
example | |
---- | |
``` | |
# regular fastapi setup | |
root = fastapi.FastAPI() | |
@root.get('/some/path') | |
... | |
...code... | |
... | |
@root.get('/some/other/path') | |
... | |
...code... | |
... | |
... some static files maybe ? | |
root.mount('/some/staticfiles') | |
... | |
...code... | |
... | |
# moment of truth | |
from fastapi_react import frontend | |
root.mount('/', frontend(build_dir='build')) # we are MOUNTING it! | |
... | |
... | |
uvicorn.run(root, port=8080) # maybe ? | |
``` | |
""" | |
def frontend(build_dir="./build"): | |
""" | |
FASTAPI ROUTER FOR REACT FRONTEND | |
:param build_dir: the path to your build folder for react | |
we are assuming the "static" folder lives within your build folder | |
if not, change it some lines below | |
:return: fastapi.FastAPI | |
""" | |
import pathlib | |
import fastapi.exceptions | |
from fastapi import FastAPI, Request, Response | |
from fastapi.staticfiles import StaticFiles | |
build_dir = pathlib.Path(build_dir) | |
react = FastAPI(openapi_url="") | |
react.mount('/static', StaticFiles(directory=build_dir / "static")) | |
@react.get('/{path:path}') | |
async def handle_catch_all(request: Request, path): | |
if path and path != "/": | |
disk_path = build_dir / path | |
if disk_path.exists(): | |
return Response(disk_path.read_bytes(), 200) | |
else: | |
if disk_path.is_file(): | |
raise fastapi.exceptions.HTTPException(404) | |
return Response((build_dir / "index.html").read_bytes(), 200) | |
return react |
Then you leave out many other filetypes , like fonts, png, jpg etc).
Actually this gist outdated already.
Here's a better one, which also handles all file types.
from pathlib import Path
FRONTEND_DIST = Path( "to your dist folder")
router = APIRouter()
@router.get('/{path:path}')
async def frontend_handler(path: str):
fp = FRONTEND_DIST / path
if not fp.exists():
fp = FRONTEND_DIST / "index.html"
return fastapi.responses.FileResponse(fp)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Great but I had to add the correct mime for this to render in Safari: