Files
privateGPT/private_gpt/global_handler.py
Javier Martinez 183cd03857 feat!: PrivateGPT revamp v1 (#2230)
* feat!: PrivateGPT revamp v1

* chore(docs): update nodejs
2026-06-02 16:55:46 +02:00

78 lines
2.6 KiB
Python

import logging
from typing import Any
from fastapi import Request
from fastapi.encoders import jsonable_encoder
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from starlette.types import ASGIApp, Receive, Scope, Send
from private_gpt.events.event_errors import Errors
from private_gpt.events.models import FatalError
logger = logging.getLogger(__name__)
def _fatal_error_payload(error: BaseException) -> tuple[int, dict[str, Any]]:
wrapped_exception = Errors.build(error)
payload = jsonable_encoder(FatalError.from_exception(error).model_dump())
explanation = payload.get("error", {}).get("detail", {}).get("explanation")
if explanation is not None:
payload["detail"] = explanation
return wrapped_exception.status_code, payload
class ExceptionMiddleware:
def __init__(self, app: ASGIApp):
self.app = app
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
if scope["type"] != "http":
await self.app(scope, receive, send)
return
async def send_wrapper(message: Any) -> None:
await send(message)
try:
await self.app(scope, receive, send_wrapper)
except Exception as exc:
logger.error("Unhandled exception occurred", exc_info=exc)
response = self._create_error_response(exc)
await response(scope, receive, send)
def _create_error_response(self, exc: Exception) -> JSONResponse:
"""Create appropriate error response based on exception type."""
status_code, fatal_error = _fatal_error_payload(exc)
return JSONResponse(
status_code=status_code,
content=jsonable_encoder(fatal_error),
)
async def request_validation_exception_handler(
request: Request, exc: RequestValidationError
) -> JSONResponse:
del request # Request currently unused.
wrapped_exception = Errors.InvalidRequest(
"Request validation failed",
event_code=Errors.Codes.INVALID_REQUEST_ERROR,
status_code=400,
original_exception=exc,
)
_, payload = _fatal_error_payload(wrapped_exception)
return JSONResponse(status_code=400, content=jsonable_encoder(payload))
async def request_validation_exception_adapter(
request: Request, exc: Exception
) -> JSONResponse:
if isinstance(exc, RequestValidationError):
return await request_validation_exception_handler(request, exc)
status_code, payload = _fatal_error_payload(exc)
return JSONResponse(
status_code=status_code,
content=jsonable_encoder(payload),
)