[New Feature] Rest API implementation to showcase the OpenDBM features

This commit is contained in:
Rudy Haryanto
2022-10-04 03:07:29 +07:00
parent a574bc6870
commit 92e08860a8
41 changed files with 2576 additions and 0 deletions

View File

View File

@@ -0,0 +1,51 @@
from fastapi import Request
from starlette.responses import JSONResponse
class AppExceptionCase(Exception):
def __init__(self, status_code: int, context: dict):
self.exception_case = self.__class__.__name__
self.status_code = status_code
self.context = context
def __str__(self):
return (
f"<AppException {self.exception_case} - "
+ f"status_code={self.status_code} - context={self.context}>"
)
async def app_exception_handler(request: Request, exc: AppExceptionCase):
return JSONResponse(
status_code=exc.status_code,
content={
"app_exception": exc.exception_case,
"context": exc.context,
},
)
class AppException(object):
class FooCreateItem(AppExceptionCase):
def __init__(self, context: dict = None):
"""
Item creation failed
"""
status_code = 500
AppExceptionCase.__init__(self, status_code, context)
class FooGetItem(AppExceptionCase):
def __init__(self, context: dict = None):
"""
Item not found
"""
status_code = 404
AppExceptionCase.__init__(self, status_code, context)
class FooItemRequiresAuth(AppExceptionCase):
def __init__(self, context: dict = None):
"""
Item is not public and requires auth
"""
status_code = 401
AppExceptionCase.__init__(self, status_code, context)

View File

@@ -0,0 +1,4 @@
from utils.app_exceptions import AppException
print([e for e in dir(AppException) if "__" not in e])
# ['FooCreateItem', 'FooGetItem', 'FooItemRequiresAuth']

View File

@@ -0,0 +1,22 @@
from fastapi.encoders import jsonable_encoder
from fastapi.exceptions import RequestValidationError
from starlette.exceptions import HTTPException
from starlette.requests import Request
from starlette.responses import JSONResponse
from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY
async def http_exception_handler(
request: Request, exc: HTTPException
) -> JSONResponse:
return JSONResponse({"detail": exc.detail}, status_code=exc.status_code)
async def request_validation_exception_handler(
request: Request, exc: RequestValidationError
) -> JSONResponse:
return JSONResponse(
status_code=HTTP_422_UNPROCESSABLE_ENTITY,
content={"detail": jsonable_encoder(exc.errors())},
)

View File

@@ -0,0 +1,47 @@
from loguru import logger
import inspect
from utils.app_exceptions import AppExceptionCase
class ServiceResult(object):
def __init__(self, arg):
if isinstance(arg, AppExceptionCase):
self.success = False
self.exception_case = arg.exception_case
self.status_code = arg.status_code
else:
self.success = True
self.exception_case = None
self.status_code = None
self.value = arg
def __str__(self):
if self.success:
return "[Success]"
return f'[Exception] "{self.exception_case}"'
def __repr__(self):
if self.success:
return "<ServiceResult Success>"
return f"<ServiceResult AppException {self.exception_case}>"
def __enter__(self):
return self.value
def __exit__(self, *kwargs):
pass
def caller_info() -> str:
info = inspect.getframeinfo(inspect.stack()[2][0])
return f"{info.filename}:{info.function}:{info.lineno}"
def handle_result(result: ServiceResult):
if not result.success:
with result as exception:
logger.error(f"{exception} | caller={caller_info()}")
raise exception
with result as result:
return result