38 lines
1.3 KiB
Python
38 lines
1.3 KiB
Python
"""将 Vue 前端构建产物挂载到 FastAPI,实现单端口 Web 访问。"""
|
|
from pathlib import Path
|
|
|
|
from fastapi import FastAPI, HTTPException
|
|
from fastapi.responses import FileResponse
|
|
from fastapi.staticfiles import StaticFiles
|
|
|
|
|
|
def mount_frontend(app: FastAPI, static_dir: Path) -> bool:
|
|
"""挂载 frontend/dist。成功返回 True,目录不存在返回 False。"""
|
|
static_dir = static_dir.resolve()
|
|
index = static_dir / "index.html"
|
|
if not index.is_file():
|
|
return False
|
|
|
|
assets_dir = static_dir / "assets"
|
|
if assets_dir.is_dir():
|
|
app.mount("/assets", StaticFiles(directory=assets_dir), name="assets")
|
|
|
|
@app.get("/", include_in_schema=False)
|
|
async def serve_index():
|
|
return FileResponse(index)
|
|
|
|
@app.get("/{filename}", include_in_schema=False)
|
|
async def serve_root_static(filename: str):
|
|
if filename.startswith("api") or filename in ("docs", "redoc", "openapi.json"):
|
|
raise HTTPException(status_code=404, detail="Not Found")
|
|
file_path = (static_dir / filename).resolve()
|
|
try:
|
|
file_path.relative_to(static_dir)
|
|
except ValueError:
|
|
raise HTTPException(status_code=404, detail="Not Found")
|
|
if file_path.is_file():
|
|
return FileResponse(file_path)
|
|
return FileResponse(index)
|
|
|
|
return True
|