""" 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, } }, )