Fix architecture issues from todolist

- Add documentation warnings for in-memory rate limiting and failed login attempts
- Consolidate duplicate health endpoints into api/health.py
- Fix CLI to use correct async rescan method names
- Update download.py and anime.py to use custom exception classes
- Add WebSocket room validation and rate limiting
This commit is contained in:
2025-12-15 14:23:41 +01:00
parent 54790a7ebb
commit 27108aacda
13 changed files with 303 additions and 255 deletions

View File

@@ -8,6 +8,17 @@ Responsibilities:
This middleware is intentionally lightweight and synchronous.
For production use consider a distributed rate limiter (Redis) and
a proper token revocation store.
WARNING - SINGLE PROCESS LIMITATION:
Rate limiting state is stored in memory dictionaries which RESET when
the process restarts. This means:
- Attackers can bypass rate limits by triggering a process restart
- Rate limits are not shared across multiple workers/processes
For production deployments, consider:
- Using Redis-backed rate limiting (e.g., slowapi with Redis)
- Running behind a reverse proxy with rate limiting (nginx, HAProxy)
- Using a dedicated rate limiting service
"""
from __future__ import annotations

View File

@@ -15,6 +15,7 @@ from src.server.exceptions import (
AniWorldAPIException,
AuthenticationError,
AuthorizationError,
BadRequestError,
ConflictError,
NotFoundError,
RateLimitError,
@@ -127,6 +128,26 @@ def register_exception_handlers(app: FastAPI) -> None:
),
)
@app.exception_handler(BadRequestError)
async def bad_request_error_handler(
request: Request, exc: BadRequestError
) -> JSONResponse:
"""Handle bad request errors (400)."""
logger.info(
f"Bad request error: {exc.message}",
extra={"details": exc.details, "path": str(request.url.path)},
)
return JSONResponse(
status_code=exc.status_code,
content=create_error_response(
status_code=exc.status_code,
error=exc.error_code,
message=exc.message,
details=exc.details,
request_id=getattr(request.state, "request_id", None),
),
)
@app.exception_handler(NotFoundError)
async def not_found_error_handler(
request: Request, exc: NotFoundError