| 1852 | |
| 1853 | |
| 1854 | class _FrontendStaticFiles(StaticFiles): |
| 1855 | def __init__( |
| 1856 | self, |
| 1857 | *, |
| 1858 | directory: str | os.PathLike[str], |
| 1859 | fallback: Literal["auto", "index.html", "404.html"] | None, |
| 1860 | check_dir: bool = True, |
| 1861 | ) -> None: |
| 1862 | self.fallback = fallback |
| 1863 | if check_dir and not os.path.isdir(directory): |
| 1864 | raise RuntimeError( |
| 1865 | f"Frontend directory '{directory}' does not exist. " |
| 1866 | f"Resolved absolute path: '{_get_resolved_absolute_path(directory)}'" |
| 1867 | ) |
| 1868 | super().__init__( |
| 1869 | directory=directory, |
| 1870 | html=True, |
| 1871 | check_dir=check_dir, |
| 1872 | follow_symlink=False, |
| 1873 | ) |
| 1874 | if check_dir and fallback in {"index.html", "404.html"}: |
| 1875 | self._check_fallback_file(fallback) |
| 1876 | |
| 1877 | def _check_fallback_file(self, fallback: str) -> None: |
| 1878 | _, stat_result = self.lookup_path(fallback) |
| 1879 | if stat_result is None or not stat.S_ISREG(stat_result.st_mode): |
| 1880 | raise RuntimeError( |
| 1881 | f"Frontend fallback file '{fallback}' does not exist in " |
| 1882 | f"directory '{self.directory}'. Resolved absolute directory: " |
| 1883 | f"'{self._get_resolved_directory()}'" |
| 1884 | ) |
| 1885 | |
| 1886 | def _get_resolved_directory(self) -> str: |
| 1887 | assert self.directory is not None |
| 1888 | return _get_resolved_absolute_path(self.directory) |
| 1889 | |
| 1890 | def get_path(self, scope: Scope) -> str: |
| 1891 | path = _get_fastapi_scope(scope).get(_FASTAPI_FRONTEND_PATH_KEY, "") |
| 1892 | assert isinstance(path, str) |
| 1893 | return os.path.normpath(os.path.join(*path.split("/"))) |
| 1894 | |
| 1895 | async def get_response(self, path: str, scope: Scope) -> Response: |
| 1896 | if scope["method"] not in ("GET", "HEAD"): |
| 1897 | if await self._lookup_static_resource(path) is not None: |
| 1898 | raise HTTPException(status_code=405) |
| 1899 | raise HTTPException(status_code=404) |
| 1900 | |
| 1901 | static_resource = await self._lookup_static_resource(path) |
| 1902 | if static_resource is not None: |
| 1903 | full_path, stat_result, is_directory_index = static_resource |
| 1904 | if is_directory_index and not scope["path"].endswith("/"): |
| 1905 | url = URL(scope=scope) |
| 1906 | url = url.replace(path=url.path + "/") |
| 1907 | return RedirectResponse(url=url) |
| 1908 | return self.file_response(full_path, stat_result, scope) |
| 1909 | |
| 1910 | if self.fallback == "404.html" or ( |
| 1911 | self.fallback == "auto" and self._fallback_file_exists("404.html") |
no outgoing calls
no test coverage detected
searching dependent graphs…