From 8a2d68ed6fed92428a94fe352dd37f9a2a7f938c Mon Sep 17 00:00:00 2001 From: Slipstream Date: Wed, 14 May 2025 17:43:24 -0600 Subject: [PATCH] feat: Enhance exception handling for openrouterkey endpoint with improved path processing and logging --- api_service/api_server.py | 69 ++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 37 deletions(-) diff --git a/api_service/api_server.py b/api_service/api_server.py index a4592af..b3e2470 100644 --- a/api_service/api_server.py +++ b/api_service/api_server.py @@ -402,32 +402,47 @@ app = FastAPI(title="Unified API Service", lifespan=lifespan, debug=True) @app.exception_handler(StarletteHTTPException) async def teapot_override(request: Request, exc: StarletteHTTPException): - # Use request.scope['path'] for a more direct path representation and ensure it's lowercased. - # It's possible request.url.path might have subtle differences in some edge cases. try: - # The path from the scope is usually the most reliable raw path. + # Get path from scope, strip trailing slash, and lowercase request_path_from_scope = request.scope.get('path', "") - path_lower = request_path_from_scope.lower() - except Exception as e: - # Fallback in case scope or path is unusual, though highly unlikely. - log.error(f"Error accessing request.scope['path'] in teapot_override: {e}, falling back to request.url.path") - path_lower = str(request.url.path).lower() + # Ensure it's a string before calling rstrip + if not isinstance(request_path_from_scope, str): + request_path_from_scope = str(request_path_from_scope) + + path_processed = request_path_from_scope.rstrip("/").lower() - # Define the specific openrouterkey paths that should not be converted to 418 on a 404. - # These are the exact paths where the endpoints are mounted. - exact_openrouterkey_paths = [ + except Exception as e: + log.error(f"Error accessing/processing request.scope['path'] in teapot_override: {e}, falling back to request.url.path") + # Fallback, also strip trailing slash and lowercase + url_path_str = str(request.url.path) + path_processed = url_path_str.rstrip("/").lower() + + # Define the specific openrouterkey paths (normalized: no trailing slash, lowercase) + exact_openrouterkey_paths_normalized = [ "/openrouterkey", "/api/openrouterkey", "/discordapi/openrouterkey" ] - if path_lower in exact_openrouterkey_paths: + is_openrouterkey_related_path_match = path_processed in exact_openrouterkey_paths_normalized + + # Enhanced logging to understand the decision process + log.info( + f"TeapotOverride Debug: " + f"Original Request Path='{request.scope.get('path', 'N/A')}', " + f"Processed Path (path_processed)='{path_processed}', " + f"Exception Status Code={exc.status_code}, " + f"Is OpenRouterKey Related Path Match={is_openrouterkey_related_path_match}" + ) + + if is_openrouterkey_related_path_match: # For these specific openrouterkey paths, log the actual exception and re-raise it. - # This ensures that a 404 (e.g., route truly not found, or handler raises 404), - # or any other error like 403 (Forbidden) or 500 (Server Error from handler) - # is passed through as is. - log.warning(f"Exception for specific openrouterkey path '{request_path_from_scope}': {exc.status_code} - {exc.detail}") - raise exc # Re-raise the original exception + log.warning( + f"Exception for specific openrouterkey path '{request.scope.get('path', 'N/A')}' " + f"(processed as '{path_processed}'): {exc.status_code} - {exc.detail}. " + f"Re-raising original exception." + ) + raise exc # For all other paths, if a 404 occurs, convert it to a 418 teapot response. if exc.status_code == 404: @@ -664,26 +679,6 @@ for route in app.routes: async def root(): return RedirectResponse(url="https://www.youtube.com/watch?v=dQw4w9WgXcQ", status_code=301) -@app.get("/openrouterkey", response_class=PlainTextResponse) -async def openrouterkey(request: Request): - """private endpoint return openrouter api key""" - # Basic security check - auth_header = request.headers.get("Authorization") - # Use loaded setting - if not settings.MOD_LOG_API_SECRET or not auth_header or auth_header != f"Bearer {settings.MOD_LOG_API_SECRET}": - print("Unauthorized attempt to access OpenRouter key.") - raise HTTPException(status_code=403, detail="Forbidden") - - # Add debug logging - log.info(f"OpenRouter key request authorized. AI_API_KEY is {'set' if settings.AI_API_KEY else 'not set'}") - - # Check if AI_API_KEY is set - if not settings.AI_API_KEY: - log.error("AI_API_KEY is not set in environment variables") - raise HTTPException(status_code=500, detail="AI_API_KEY not configured") - - return f"{settings.AI_API_KEY}" - # Add the same endpoint to the api_app to ensure it's accessible @api_app.get("/openrouterkey", response_class=PlainTextResponse) async def api_openrouterkey(request: Request):