fix: handle directory access for static web-ui routes

When accessing /static/web-ui without trailing slash, the request would
fail with "RuntimeError: File at path ... is not a file" because:

1. The route /static/web-ui/{file_path:path} doesn't match paths without
   trailing slash (Starlette's path regex requires the /)
2. The request falls through to StaticFiles mount, which tries to serve
   the directory as a file

This fix:
- Sets html=True on StaticFiles mount to automatically redirect directory
  URLs to trailing slash versions
- Adds os.path.isdir() check to handle empty file_path gracefully

Fixes #2680

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
YueGuobin 2026-05-03 17:21:03 +08:00
parent c45f6d9416
commit 952ef66a6b
No known key found for this signature in database
2 changed files with 2 additions and 2 deletions

View File

@ -52,7 +52,7 @@ async def web_ui(file_path: str):
static = get_resource(file_path)
if static is None or not os.path.exists(static):
if static is None or not os.path.exists(static) or os.path.isdir(static):
static = get_resource(os.path.join("static", "web-ui", "index.html"))
if static is None:

View File

@ -73,7 +73,7 @@ def get_application() -> FastAPI:
application.include_router(index.router, tags=["Index"])
application.include_router(controller.router, prefix="/v3")
application.mount("/static", StaticFiles(packages=[('gns3server', 'static')]), name="static")
application.mount("/static", StaticFiles(packages=[('gns3server', 'static')], html=True), name="static")
application.mount("/v3/compute", compute_api, name="compute")
return application