From 952ef66a6b1c3686764c61ea66b603e634485d9f Mon Sep 17 00:00:00 2001 From: YueGuobin Date: Sun, 3 May 2026 17:21:03 +0800 Subject: [PATCH] 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 --- gns3server/api/routes/index.py | 2 +- gns3server/api/server.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gns3server/api/routes/index.py b/gns3server/api/routes/index.py index ebd22c096..365840b8c 100644 --- a/gns3server/api/routes/index.py +++ b/gns3server/api/routes/index.py @@ -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: diff --git a/gns3server/api/server.py b/gns3server/api/server.py index 224a8314b..196ddb504 100644 --- a/gns3server/api/server.py +++ b/gns3server/api/server.py @@ -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