stable/freqtrade/rpc/api_server/web_ui.py

60 lines
1.8 KiB
Python
Raw Normal View History

2021-01-10 09:31:05 +00:00
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'))
2021-01-10 09:31:05 +00:00
@router_ui.get('/fallback_file.html', include_in_schema=False)
async def fallback():
return FileResponse(str(Path(__file__).parent / 'ui/fallback_file.html'))
2021-07-06 05:20:05 +00:00
@router_ui.get('/ui_version', include_in_schema=False)
async def ui_version():
from freqtrade.commands.deploy_commands import read_ui_version
uibase = Path(__file__).parent / 'ui/installed/'
version = read_ui_version(uibase)
return {
"version": version if version else "not_installed",
}
2021-08-16 05:08:50 +00:00
def is_relative_to(path, base) -> bool:
# Helper function simulating behaviour of is_relative_to, which was only added in python 3.9
try:
path.relative_to(base)
except ValueError:
pass
return False
2021-01-10 09:31:05 +00:00
@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")
2021-01-31 14:37:57 +00:00
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.
2021-08-16 05:08:50 +00:00
if filename.is_file() and is_relative_to(filename, uibase):
return FileResponse(str(filename))
2021-01-10 09:31:05 +00:00
2021-01-16 09:27:15 +00:00
index_file = uibase / 'index.html'
if not index_file.is_file():
2021-01-31 14:37:57 +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
return FileResponse(str(index_file))