2021-01-10 09:31:05 +00:00
|
|
|
from pathlib import Path
|
2022-08-07 08:42:56 +00:00
|
|
|
from typing import Optional
|
2021-01-10 09:31:05 +00:00
|
|
|
|
|
|
|
from fastapi import APIRouter
|
|
|
|
from fastapi.exceptions import HTTPException
|
|
|
|
from starlette.responses import FileResponse
|
|
|
|
|
|
|
|
|
|
|
|
router_ui = APIRouter()
|
|
|
|
|
|
|
|
|
2024-05-12 14:51:11 +00:00
|
|
|
@router_ui.get("/favicon.ico", include_in_schema=False)
|
2021-01-10 09:31:05 +00:00
|
|
|
async def favicon():
|
2024-05-12 14:51:11 +00:00
|
|
|
return FileResponse(str(Path(__file__).parent / "ui/favicon.ico"))
|
2021-01-10 09:31:05 +00:00
|
|
|
|
|
|
|
|
2024-05-12 14:51:11 +00:00
|
|
|
@router_ui.get("/fallback_file.html", include_in_schema=False)
|
2021-04-07 04:55:11 +00:00
|
|
|
async def fallback():
|
2024-05-12 14:51:11 +00:00
|
|
|
return FileResponse(str(Path(__file__).parent / "ui/fallback_file.html"))
|
2021-04-07 04:55:11 +00:00
|
|
|
|
|
|
|
|
2024-05-12 14:51:11 +00:00
|
|
|
@router_ui.get("/ui_version", include_in_schema=False)
|
2021-07-06 05:20:05 +00:00
|
|
|
async def ui_version():
|
|
|
|
from freqtrade.commands.deploy_commands import read_ui_version
|
2024-05-12 14:51:11 +00:00
|
|
|
|
|
|
|
uibase = Path(__file__).parent / "ui/installed/"
|
2021-07-06 05:20:05 +00:00
|
|
|
version = read_ui_version(uibase)
|
|
|
|
|
|
|
|
return {
|
|
|
|
"version": version if version else "not_installed",
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-07-25 18:07:44 +00:00
|
|
|
def is_relative_to(path: Path, base: Path) -> bool:
|
2021-08-16 05:08:50 +00:00
|
|
|
# Helper function simulating behaviour of is_relative_to, which was only added in python 3.9
|
|
|
|
try:
|
|
|
|
path.relative_to(base)
|
2021-08-16 05:26:58 +00:00
|
|
|
return True
|
2021-08-16 05:08:50 +00:00
|
|
|
except ValueError:
|
|
|
|
pass
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
2024-05-12 14:51:11 +00:00
|
|
|
@router_ui.get("/{rest_of_path:path}", include_in_schema=False)
|
2021-01-10 09:31:05 +00:00
|
|
|
async def index_html(rest_of_path: str):
|
|
|
|
"""
|
|
|
|
Emulate path fallback to index.html.
|
|
|
|
"""
|
2024-05-12 14:51:11 +00:00
|
|
|
if rest_of_path.startswith("api") or rest_of_path.startswith("."):
|
2021-01-10 09:31:05 +00:00
|
|
|
raise HTTPException(status_code=404, detail="Not Found")
|
2024-05-12 14:51:11 +00:00
|
|
|
uibase = Path(__file__).parent / "ui/installed/"
|
2021-08-16 04:45:43 +00:00
|
|
|
filename = uibase / rest_of_path
|
|
|
|
# It's security relevant to check "relative_to".
|
|
|
|
# Without this, Directory-traversal is possible.
|
2022-08-07 08:42:56 +00:00
|
|
|
media_type: Optional[str] = None
|
2024-05-12 14:51:11 +00:00
|
|
|
if filename.suffix == ".js":
|
2022-08-07 08:42:56 +00:00
|
|
|
# Force text/javascript for .js files - Circumvent faulty system configuration
|
2024-05-12 14:51:11 +00:00
|
|
|
media_type = "application/javascript"
|
2021-08-16 05:08:50 +00:00
|
|
|
if filename.is_file() and is_relative_to(filename, uibase):
|
2022-08-07 08:42:56 +00:00
|
|
|
return FileResponse(str(filename), media_type=media_type)
|
2021-01-10 09:31:05 +00:00
|
|
|
|
2024-05-12 14:51:11 +00:00
|
|
|
index_file = uibase / "index.html"
|
2021-01-16 09:27:15 +00:00
|
|
|
if not index_file.is_file():
|
2024-05-12 14:51:11 +00:00
|
|
|
return FileResponse(str(uibase.parent / "fallback_file.html"))
|
2021-01-10 09:31:05 +00:00
|
|
|
# Fall back to index.html, as indicated by vue router docs
|
2021-01-31 13:54:58 +00:00
|
|
|
return FileResponse(str(index_file))
|