freqtrade_origin/freqtrade/rpc/api_server/web_ui.py
2024-11-08 04:37:33 +08:00

56 lines
1.8 KiB
Python

from pathlib import Path
from fastapi import APIRouter
from fastapi.exceptions import HTTPException
from starlette.responses import FileResponse
router_ui = APIRouter()
@router_ui.get("/favicon.ico", include_in_schema=False)
async def favicon():
return FileResponse(str(Path(__file__).parent / "ui/favicon.ico"))
@router_ui.get("/fallback_file.html", include_in_schema=False)
async def fallback():
return FileResponse(str(Path(__file__).parent / "ui/fallback_file.html"))
@router_ui.get("/ui_version", include_in_schema=False)
async def ui_version():
from freqtrade.commands.deploy_ui import read_ui_version
uibase = Path(__file__).parent / "ui/installed/"
version = read_ui_version(uibase)
return {
"version": version if version else "not_installed",
}
@router_ui.get("/{rest_of_path:path}", include_in_schema=False)
async def index_html(rest_of_path: str):
"""
Emulate path fallback to index.html.
"""
if rest_of_path.startswith("api") or rest_of_path.startswith("."):
raise HTTPException(status_code=404, detail="Not Found")
uibase = Path(__file__).parent / "ui/installed/"
filename = uibase / rest_of_path
# It's security relevant to check "relative_to".
# Without this, Directory-traversal is possible.
media_type: str | None = None
if filename.suffix == ".js":
# Force text/javascript for .js files - Circumvent faulty system configuration
media_type = "application/javascript"
if filename.is_file() and filename.is_relative_to(uibase):
return FileResponse(str(filename), media_type=media_type)
index_file = uibase / "index.html"
if not index_file.is_file():
return FileResponse(str(uibase.parent / "fallback_file.html"))
# Fall back to index.html, as indicated by vue router docs
return FileResponse(str(index_file))