131 lines
4.4 KiB
Python
131 lines
4.4 KiB
Python
"""
|
|
Exception handlers for the application.
|
|
"""
|
|
|
|
import logging
|
|
from typing import Any, Dict
|
|
from fastapi import FastAPI, Request, status
|
|
from fastapi.responses import JSONResponse
|
|
from fastapi.exceptions import RequestValidationError
|
|
from pydantic import ValidationError as PydanticValidationError
|
|
|
|
from app.core.exceptions import DailyJournalPromptException
|
|
from app.core.logging import setup_logging
|
|
|
|
logger = setup_logging()
|
|
|
|
|
|
def setup_exception_handlers(app: FastAPI) -> None:
|
|
"""Set up exception handlers for the FastAPI application."""
|
|
|
|
@app.exception_handler(DailyJournalPromptException)
|
|
async def daily_journal_prompt_exception_handler(
|
|
request: Request,
|
|
exc: DailyJournalPromptException,
|
|
) -> JSONResponse:
|
|
"""Handle DailyJournalPromptException."""
|
|
logger.error(f"DailyJournalPromptException: {exc.detail}")
|
|
return JSONResponse(
|
|
status_code=exc.status_code,
|
|
content={
|
|
"error": {
|
|
"type": exc.__class__.__name__,
|
|
"message": str(exc.detail),
|
|
"status_code": exc.status_code,
|
|
}
|
|
},
|
|
)
|
|
|
|
@app.exception_handler(RequestValidationError)
|
|
async def request_validation_exception_handler(
|
|
request: Request,
|
|
exc: RequestValidationError,
|
|
) -> JSONResponse:
|
|
"""Handle request validation errors."""
|
|
logger.warning(f"RequestValidationError: {exc.errors()}")
|
|
return JSONResponse(
|
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
content={
|
|
"error": {
|
|
"type": "ValidationError",
|
|
"message": "Invalid request data",
|
|
"details": exc.errors(),
|
|
"status_code": status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
}
|
|
},
|
|
)
|
|
|
|
@app.exception_handler(PydanticValidationError)
|
|
async def pydantic_validation_exception_handler(
|
|
request: Request,
|
|
exc: PydanticValidationError,
|
|
) -> JSONResponse:
|
|
"""Handle Pydantic validation errors."""
|
|
logger.warning(f"PydanticValidationError: {exc.errors()}")
|
|
return JSONResponse(
|
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
content={
|
|
"error": {
|
|
"type": "ValidationError",
|
|
"message": "Invalid data format",
|
|
"details": exc.errors(),
|
|
"status_code": status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
}
|
|
},
|
|
)
|
|
|
|
@app.exception_handler(Exception)
|
|
async def generic_exception_handler(
|
|
request: Request,
|
|
exc: Exception,
|
|
) -> JSONResponse:
|
|
"""Handle all other exceptions."""
|
|
logger.exception(f"Unhandled exception: {exc}")
|
|
return JSONResponse(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
content={
|
|
"error": {
|
|
"type": "InternalServerError",
|
|
"message": "An unexpected error occurred",
|
|
"status_code": status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
}
|
|
},
|
|
)
|
|
|
|
@app.exception_handler(404)
|
|
async def not_found_exception_handler(
|
|
request: Request,
|
|
exc: Exception,
|
|
) -> JSONResponse:
|
|
"""Handle 404 Not Found errors."""
|
|
logger.warning(f"404 Not Found: {request.url}")
|
|
return JSONResponse(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
content={
|
|
"error": {
|
|
"type": "NotFoundError",
|
|
"message": f"Resource not found: {request.url}",
|
|
"status_code": status.HTTP_404_NOT_FOUND,
|
|
}
|
|
},
|
|
)
|
|
|
|
@app.exception_handler(405)
|
|
async def method_not_allowed_exception_handler(
|
|
request: Request,
|
|
exc: Exception,
|
|
) -> JSONResponse:
|
|
"""Handle 405 Method Not Allowed errors."""
|
|
logger.warning(f"405 Method Not Allowed: {request.method} {request.url}")
|
|
return JSONResponse(
|
|
status_code=status.HTTP_405_METHOD_NOT_ALLOWED,
|
|
content={
|
|
"error": {
|
|
"type": "MethodNotAllowedError",
|
|
"message": f"Method {request.method} not allowed for {request.url}",
|
|
"status_code": status.HTTP_405_METHOD_NOT_ALLOWED,
|
|
}
|
|
},
|
|
)
|
|
|