From 86c6f1f1122511fcb56a74a82b604af4e064c565 Mon Sep 17 00:00:00 2001 From: Peter Double <134428501+solaius@users.noreply.github.com> Date: Mon, 14 Apr 2025 13:28:25 -0400 Subject: [PATCH] =?UTF-8?q?fix:=20FastAPI=20built-in=20paths=20bypass=20cu?= =?UTF-8?q?stom=20routing=20(Docs)=20and=20update=20r=E2=80=A6=20(#1841)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What does this PR do? This PR improves the server's request routing logic by ensuring built-in FastAPI paths such as `/docs`, `/redoc`, `/openapi.json`, `/favicon.ico`, and `/static` bypass the custom `TracingMiddleware`. This prevents unnecessary tracing logic for documentation and static file requests, ensuring better performance and cleaner logs. Additionally, it adds proper metadata (`title`, `description`, and `version`) to the FastAPI application initialization and updates the requirements document accordingly. [//]: # (Closes #1822 ) --- ## Test Plan - Ran the server locally with `uvicorn` using the provided `run.yaml` config - Verified that: - FastAPI docs (`/docs`, `/redoc`) load correctly without triggering the custom tracing middleware - All other routes still go through the middleware and trace logic - Application metadata appears as expected in the OpenAPI docs To reproduce: 1. Start the server with `python server.py --template ` 2. Navigate to `/docs` and `/redoc` 3. Confirm that no extra trace headers are added for those routes 4. Confirm other API endpoints behave as expected and include `x-trace-id` in the response headers [//]: # (## Documentation) --- Froze the requirements file to include many of the other libraries that have been added in the past few releases to make install easier. --------- Co-authored-by: Sébastien Han --- llama_stack/distribution/server/server.py | 24 +++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/llama_stack/distribution/server/server.py b/llama_stack/distribution/server/server.py index d7ef37c26..9bbb2ce88 100644 --- a/llama_stack/distribution/server/server.py +++ b/llama_stack/distribution/server/server.py @@ -229,15 +229,30 @@ class TracingMiddleware: def __init__(self, app, impls): self.app = app self.impls = impls + # FastAPI built-in paths that should bypass custom routing + self.fastapi_paths = ("/docs", "/redoc", "/openapi.json", "/favicon.ico", "/static") async def __call__(self, scope, receive, send): if scope.get("type") == "lifespan": return await self.app(scope, receive, send) path = scope.get("path", "") + + # Check if the path is a FastAPI built-in path + if path.startswith(self.fastapi_paths): + # Pass through to FastAPI's built-in handlers + logger.debug(f"Bypassing custom routing for FastAPI built-in path: {path}") + return await self.app(scope, receive, send) + if not hasattr(self, "endpoint_impls"): self.endpoint_impls = initialize_endpoint_impls(self.impls) - _, _, trace_path = find_matching_endpoint(scope.get("method", "GET"), path, self.endpoint_impls) + + try: + _, _, trace_path = find_matching_endpoint(scope.get("method", "GET"), path, self.endpoint_impls) + except ValueError: + # If no matching endpoint is found, pass through to FastAPI + logger.debug(f"No matching endpoint found for path: {path}, falling back to FastAPI") + return await self.app(scope, receive, send) trace_context = await start_trace(trace_path, {"__location__": "server", "raw_path": path}) @@ -388,7 +403,12 @@ def main(args: Optional[argparse.Namespace] = None): safe_config = redact_sensitive_fields(config.model_dump()) logger.info(yaml.dump(safe_config, indent=2)) - app = FastAPI(lifespan=lifespan) + app = FastAPI( + lifespan=lifespan, + docs_url="/docs", + redoc_url="/redoc", + openapi_url="/openapi.json", + ) if not os.environ.get("LLAMA_STACK_DISABLE_VERSION_CHECK"): app.add_middleware(ClientVersionMiddleware)