feat: initial commit
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
from fastapi import Request, status
|
||||
from fastapi.responses import JSONResponse
|
||||
from fastapi.exceptions import RequestValidationError
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
from starlette.exceptions import HTTPException as StarletteHTTPException
|
||||
import traceback
|
||||
|
||||
from exceptions import (
|
||||
ApiException,
|
||||
BusinessValidationException,
|
||||
ValidationException
|
||||
)
|
||||
from schemas.ApiResponse import ApiResponse
|
||||
|
||||
|
||||
class ErrorHandlerMiddleware(BaseHTTPMiddleware):
|
||||
"""Middleware for handling exceptions globally in the application."""
|
||||
|
||||
async def dispatch(self, request: Request, call_next):
|
||||
try:
|
||||
return await call_next(request)
|
||||
except Exception as exc:
|
||||
return self.handle_exception(exc)
|
||||
|
||||
def handle_exception(self, exc: Exception) -> JSONResponse:
|
||||
if isinstance(exc, ApiException):
|
||||
return JSONResponse(
|
||||
status_code=exc.status_code,
|
||||
content=ApiResponse.from_api_exception(exc)
|
||||
)
|
||||
elif isinstance(exc, StarletteHTTPException):
|
||||
return JSONResponse(
|
||||
status_code=exc.status_code,
|
||||
content=ApiResponse(
|
||||
message=str(exc.detail),
|
||||
error=str(traceback.format_exc())
|
||||
).model_dump(exclude_none=True)
|
||||
)
|
||||
elif isinstance(exc, (ValidationException, BusinessValidationException)):
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
content=ApiResponse(
|
||||
message=str(exc),
|
||||
error=str(traceback.format_exc())
|
||||
).model_dump(exclude_none=True)
|
||||
)
|
||||
elif isinstance(exc, RequestValidationError):
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
content=ApiResponse(
|
||||
message="Validation error",
|
||||
error=str(exc.errors())
|
||||
).model_dump(exclude_none=True)
|
||||
)
|
||||
else:
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
content=ApiResponse(
|
||||
message=str(exc),
|
||||
error=str(traceback.format_exc())
|
||||
).model_dump(exclude_none=True)
|
||||
)
|
||||
|
||||
|
||||
# Exception handlers for FastAPI
|
||||
def configure_exception_handlers(app):
|
||||
"""Configure exception handlers for the FastAPI application."""
|
||||
|
||||
@app.exception_handler(ApiException)
|
||||
async def api_exception_handler(request: Request, exc: ApiException):
|
||||
return JSONResponse(
|
||||
status_code=exc.status_code,
|
||||
content=ApiResponse.from_api_exception(exc)
|
||||
)
|
||||
|
||||
@app.exception_handler(RequestValidationError)
|
||||
async def validation_exception_handler(request: Request, exc: RequestValidationError):
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
content=ApiResponse(
|
||||
message="Validation error",
|
||||
error=str(exc.errors())
|
||||
).model_dump(exclude_none=True)
|
||||
)
|
||||
|
||||
@app.exception_handler(StarletteHTTPException)
|
||||
async def http_exception_handler(request: Request, exc: StarletteHTTPException):
|
||||
return JSONResponse(
|
||||
status_code=exc.status_code,
|
||||
content=ApiResponse(
|
||||
message=str(exc.detail),
|
||||
error=str(traceback.format_exc())
|
||||
).model_dump(exclude_none=True)
|
||||
)
|
||||
|
||||
@app.exception_handler(BusinessValidationException)
|
||||
async def business_validation_exception_handler(request: Request, exc: BusinessValidationException):
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
content=ApiResponse(
|
||||
message=str(exc),
|
||||
error=str(traceback.format_exc())
|
||||
).model_dump(exclude_none=True)
|
||||
)
|
||||
|
||||
@app.exception_handler(ValidationException)
|
||||
async def custom_validation_exception_handler(request: Request, exc: ValidationException):
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
content=ApiResponse(
|
||||
message=str(exc),
|
||||
error=str(traceback.format_exc())
|
||||
).model_dump(exclude_none=True)
|
||||
)
|
||||
|
||||
@app.exception_handler(Exception)
|
||||
async def general_exception_handler(request: Request, exc: Exception):
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
content=ApiResponse(
|
||||
message=str(exc),
|
||||
error=str(traceback.format_exc())
|
||||
).model_dump(exclude_none=True)
|
||||
)
|
||||
@@ -0,0 +1,27 @@
|
||||
from fastapi import HTTPException, Depends
|
||||
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
||||
from services.jwtService import verify_jwt_token
|
||||
from services.userServices import UserServices
|
||||
from fastapi import Request
|
||||
|
||||
security = HTTPBearer()
|
||||
|
||||
async def auth_required(request: Request ,credentials: HTTPAuthorizationCredentials = Depends(security)):
|
||||
"""
|
||||
Dependency function to verify JWT token for protected routes
|
||||
"""
|
||||
if credentials.scheme != "Bearer":
|
||||
raise HTTPException(status_code=401, detail="Invalid authentication scheme")
|
||||
|
||||
payload = verify_jwt_token(credentials.credentials)
|
||||
if payload is None:
|
||||
raise HTTPException(status_code=401, detail="Invalid authentication token")
|
||||
|
||||
# Get user from database
|
||||
user = UserServices().get_user(payload["user_id"])
|
||||
|
||||
# set user to request state
|
||||
request.state.user = user
|
||||
request.state.payload = payload
|
||||
|
||||
return True
|
||||
Reference in New Issue
Block a user