🐛 Fix blocking frontend fallback file checks (#16503)

This commit is contained in:
Sebastián Ramírez authored and GitHub committed 2026-10-15 15:22:29 +02:00
1 parent db04f5b7ed
commit d0282a388b
2 files changed
+20 -5

No files matched your search

+7 -4
View File
@@ -2004,13 +2004,16 @@ class _FrontendStaticFiles(StaticFiles):
return self.file_response(full_path, stat_result, scope)
if self.fallback == "404.html" or (
self.fallback == "auto" and self._fallback_file_exists("404.html")
self.fallback == "auto" and await self._fallback_file_exists("404.html")
):
return await self._fallback_response("404.html", scope, status_code=404)
if (
self.fallback == "index.html"
or (self.fallback == "auto" and self._fallback_file_exists("index.html"))
or (
self.fallback == "auto"
and await self._fallback_file_exists("index.html")
)
) and _is_frontend_navigation_request(scope):
return await self._fallback_response("index.html", scope, status_code=200)
@@ -2043,8 +2046,8 @@ class _FrontendStaticFiles(StaticFiles):
return full_path, stat_result, True
return None
def _fallback_file_exists(self, fallback: str) -> bool:
_, stat_result = self.lookup_path(fallback)
async def _fallback_file_exists(self, fallback: str) -> bool:
_, stat_result = await run_in_threadpool(self.lookup_path, fallback)
return stat_result is not None and stat.S_ISREG(stat_result.st_mode)
async def _fallback_response(
+13 -1
View File
@@ -1,3 +1,4 @@
import asyncio
import errno
import os
import runpy
@@ -775,11 +776,22 @@ def test_auto_fallback_prefers_404_over_index(tmp_path: Path):
assert response.text == "missing"
def test_auto_fallback_uses_index_when_404_is_missing(tmp_path: Path):
def test_auto_fallback_uses_index_when_404_is_missing(monkeypatch, tmp_path: Path):
dist = tmp_path / "dist"
write_file(dist / "index.html", "app shell")
app = FastAPI()
app.frontend("/", directory=dist)
frontend_routes = app.router._frontend_routes
assert frontend_routes is not None
static_files = frontend_routes.routes[0].app
original_lookup_path = static_files.lookup_path
def lookup_path(path: str):
with pytest.raises(RuntimeError, match="no running event loop"):
asyncio.get_running_loop()
return original_lookup_path(path)
monkeypatch.setattr(static_files, "lookup_path", lookup_path)
response = TestClient(app).get("/dashboard", headers={"accept": "text/html"})