mirror of
https://github.com/bringout/oca-technical.git
synced 2026-04-18 13:32:01 +02:00
78 lines
3 KiB
Python
78 lines
3 KiB
Python
# Copyright 2022 ACSONE SA/NV
|
|
# License LGPL-3.0 or later (http://www.gnu.org/licenses/LGPL).
|
|
from typing import Tuple
|
|
|
|
from starlette import status
|
|
from starlette.exceptions import HTTPException, WebSocketException
|
|
from starlette.middleware.errors import ServerErrorMiddleware
|
|
from starlette.middleware.exceptions import ExceptionMiddleware
|
|
from starlette.responses import JSONResponse
|
|
from starlette.websockets import WebSocket
|
|
from werkzeug.exceptions import HTTPException as WerkzeugHTTPException
|
|
|
|
from odoo.exceptions import AccessDenied, AccessError, MissingError, UserError
|
|
|
|
from fastapi import Request
|
|
from fastapi.encoders import jsonable_encoder
|
|
from fastapi.exceptions import RequestValidationError, WebSocketRequestValidationError
|
|
from fastapi.utils import is_body_allowed_for_status_code
|
|
|
|
|
|
def convert_exception_to_status_body(exc: Exception) -> Tuple[int, dict]:
|
|
body = {}
|
|
status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
|
|
details = "Internal Server Error"
|
|
|
|
if isinstance(exc, WerkzeugHTTPException):
|
|
status_code = exc.code
|
|
details = exc.description
|
|
elif isinstance(exc, HTTPException):
|
|
status_code = exc.status_code
|
|
details = exc.detail
|
|
elif isinstance(exc, RequestValidationError):
|
|
status_code = status.HTTP_422_UNPROCESSABLE_ENTITY
|
|
details = jsonable_encoder(exc.errors())
|
|
elif isinstance(exc, WebSocketRequestValidationError):
|
|
status_code = status.WS_1008_POLICY_VIOLATION
|
|
details = jsonable_encoder(exc.errors())
|
|
elif isinstance(exc, (AccessDenied, AccessError)):
|
|
status_code = status.HTTP_403_FORBIDDEN
|
|
details = "AccessError"
|
|
elif isinstance(exc, MissingError):
|
|
status_code = status.HTTP_404_NOT_FOUND
|
|
details = "MissingError"
|
|
elif isinstance(exc, UserError):
|
|
status_code = status.HTTP_400_BAD_REQUEST
|
|
details = exc.args[0]
|
|
|
|
if is_body_allowed_for_status_code(status_code):
|
|
# use the same format as in
|
|
# fastapi.exception_handlers.http_exception_handler
|
|
body = {"detail": details}
|
|
return status_code, body
|
|
|
|
|
|
# we need to monkey patch the ServerErrorMiddleware and ExceptionMiddleware classes
|
|
# to ensure that all the exceptions that are handled by these specific
|
|
# middlewares are let to bubble up to the retrying mechanism and the
|
|
# dispatcher error handler to ensure that appropriate action are taken
|
|
# regarding the transaction, environment, and registry. These middlewares
|
|
# are added by default by FastAPI when creating an application and it's not
|
|
# possible to remove them. So we need to monkey patch them.
|
|
|
|
|
|
def pass_through_exception_handler(
|
|
self, request: Request, exc: Exception
|
|
) -> JSONResponse:
|
|
raise exc
|
|
|
|
|
|
def pass_through_websocket_exception_handler(
|
|
self, websocket: WebSocket, exc: WebSocketException
|
|
) -> None:
|
|
raise exc
|
|
|
|
|
|
ServerErrorMiddleware.error_response = pass_through_exception_handler
|
|
ExceptionMiddleware.http_exception = pass_through_exception_handler
|
|
ExceptionMiddleware.websocket_exception = pass_through_websocket_exception_handler
|