feat: Enhance exception handling for openrouterkey endpoint with improved path processing and logging

This commit is contained in:
Slipstream 2025-05-14 17:43:24 -06:00
parent 161707f71d
commit 8a2d68ed6f
Signed by: slipstream
GPG Key ID: 13E498CE010AC6FD

View File

@ -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):