Fixed base path issues

This commit is contained in:
Donkie
2024-05-22 20:15:39 +02:00
parent 620febc3ab
commit 26f5eaa2f7

View File

@@ -4,13 +4,20 @@
import logging import logging
import os import os
from collections.abc import MutableMapping
from pathlib import Path from pathlib import Path
from typing import Union from typing import Any, Union
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
from starlette.datastructures import Headers
from starlette.responses import FileResponse, Response
from starlette.staticfiles import NotModifiedResponse
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
PathLike = Union[str, "os.PathLike[str]"]
Scope = MutableMapping[str, Any]
class SinglePageApplication(StaticFiles): class SinglePageApplication(StaticFiles):
"""Serve a single page application.""" """Serve a single page application."""
@@ -20,6 +27,45 @@ class SinglePageApplication(StaticFiles):
super().__init__(directory=directory, packages=None, html=True, check_dir=True) super().__init__(directory=directory, packages=None, html=True, check_dir=True)
self.base_path = base_path.removeprefix("/") self.base_path = base_path.removeprefix("/")
self.load_and_tweak_index_file()
def load_and_tweak_index_file(self) -> None:
"""Load index.html and tweak it by replacing all asset paths."""
# Open index.html located in self.directory/index.html
if not self.directory:
return
with (Path(self.directory) / "index.html").open() as f:
html = f.read()
# Replace all paths that start with "./" with f"/{self.base_path}"
base_path = "/" if len(self.base_path.strip()) == 0 else f"/{self.base_path}/"
self.html = html.replace('"./', f'"{base_path}')
def file_response(
self,
full_path: PathLike,
stat_result: os.stat_result,
scope: Scope,
status_code: int = 200,
) -> Response:
"""Overriden default file_response.
Works the same way, but if the client requests any index.html, we will return our tweaked index.html.
The tweaked index.html has all asset paths updated with the base path.
"""
method = scope["method"]
request_headers = Headers(scope=scope)
# If full_path points to a index.html, return our tweaked index.html
if Path(full_path).name == "index.html":
return Response(self.html, status_code=status_code, media_type="text/html")
response = FileResponse(full_path, status_code=status_code, stat_result=stat_result, method=method)
if self.is_not_modified(response.headers, request_headers):
return NotModifiedResponse(response.headers)
return response
def lookup_path(self, path: str) -> tuple[str, Union[os.stat_result, None]]: def lookup_path(self, path: str) -> tuple[str, Union[os.stat_result, None]]:
"""Return index.html if the requested file cannot be found.""" """Return index.html if the requested file cannot be found."""
path = path.removeprefix(self.base_path).removeprefix("/") path = path.removeprefix(self.base_path).removeprefix("/")