114 lines
3.1 KiB
Python
114 lines
3.1 KiB
Python
from fastapi import FastAPI, HTTPException, Request, Response, status
|
|
from fastapi.responses import JSONResponse
|
|
|
|
|
|
class FastShipError(Exception):
|
|
"""Base exception for all exceptions in fastship api"""
|
|
# status_code to be returned for this exception
|
|
# when it is handled
|
|
status = status.HTTP_400_BAD_REQUEST
|
|
|
|
|
|
class EntityNotFound(FastShipError):
|
|
"""Entity not found in database"""
|
|
|
|
status = status.HTTP_404_NOT_FOUND
|
|
|
|
|
|
class BadPassword(FastShipError):
|
|
"""Password is not strong enough or invalid"""
|
|
|
|
status = status.HTTP_400_BAD_REQUEST
|
|
|
|
|
|
class ClientNotAuthorized(FastShipError):
|
|
"""Client is not authorized to perform the action"""
|
|
|
|
status = status.HTTP_401_UNAUTHORIZED
|
|
|
|
|
|
class ClientNotVerified(FastShipError):
|
|
"""Client is not verified"""
|
|
|
|
status = status.HTTP_401_UNAUTHORIZED
|
|
|
|
|
|
class NothingToUpdate(FastShipError):
|
|
"""No data provided to update"""
|
|
|
|
|
|
class BadCredentials(FastShipError):
|
|
"""User email or password is incorrect"""
|
|
|
|
status = status.HTTP_401_UNAUTHORIZED
|
|
|
|
|
|
class InvalidToken(FastShipError):
|
|
"""Access token is invalid or expired"""
|
|
|
|
status = status.HTTP_401_UNAUTHORIZED
|
|
|
|
|
|
class DeliveryPartnerNotAvailable(FastShipError):
|
|
"""Delivery partner/s do not service the destination"""
|
|
|
|
status = status.HTTP_406_NOT_ACCEPTABLE
|
|
|
|
|
|
class DeliveryPartnerCapacityExceeded(FastShipError):
|
|
"""Delivery partner has reached their max handling capacity"""
|
|
|
|
status = status.HTTP_406_NOT_ACCEPTABLE
|
|
|
|
|
|
def _get_handler(status: int, detail: str):
|
|
# Define
|
|
def handler(request: Request, exception: Exception) -> Response:
|
|
# DEBUG PRINT STATEMENT 👇
|
|
from rich import print, panel
|
|
print(
|
|
panel.Panel(
|
|
exception.__class__.__name__,
|
|
title="Handled Exception",
|
|
border_style="red",
|
|
),
|
|
)
|
|
# DEBUG PRINT STATEMENT 👆
|
|
|
|
# Raise HTTPException with given status and detail
|
|
# can return JSONResponse as well
|
|
raise HTTPException(
|
|
status_code=status,
|
|
detail=detail,
|
|
)
|
|
# Return ExceptionHandler required with given
|
|
# status and detail for HTTPExcetion above
|
|
return handler
|
|
|
|
|
|
def add_exception_handlers(app: FastAPI):
|
|
# Get all subclass of 👇, our custom exceptions
|
|
exception_classes = FastShipError.__subclasses__()
|
|
|
|
for exception_class in exception_classes:
|
|
# Add exception handler
|
|
app.add_exception_handler(
|
|
# Custom exception class
|
|
exception_class,
|
|
# Get handler function
|
|
_get_handler(
|
|
status=exception_class.status,
|
|
detail=exception_class.__doc__,
|
|
),
|
|
)
|
|
|
|
@app.exception_handler(status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
def internal_server_error_handler(request, exception):
|
|
return JSONResponse(
|
|
content={"detail": "Something went wrong..."},
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
headers={
|
|
"X-Error": f"{exception}",
|
|
}
|
|
)
|
|
|