-
-
Notifications
You must be signed in to change notification settings - Fork 12
Description
We should support defining custom exception catalogs in a single exceptions.yaml that can be imported to generate enums and exported from existing enums.
Why
• Keep business error semantics in source control as a reviewable spec.
• Make localisation optional and incremental.
• Enable consistent, typed responses across the codebase.
from pydantic import BaseModel, Field
from fastapi import FastAPI, Path
from api_exception import BaseExceptionCode, APIException, ResponseMode, APIResponse
'''
This can be located __init__.py.
'''
app = FastAPI()
register_exception_handlers(app)
'''
This can be located under the projects' enum folder. Can be named as 'exceptions.py' or 'error.py'.
Or it can be directly packaged as 'exception' or 'error' if the project is massive. Then you can have something like 'auth.py', 'user.py'.
'''
AuthException(BaseExceptionCode):
AUTH_FAILED = ("AUTH-100", "User is not able to log in.", "Password is incorrect")
UserException(BaseExceptionCode):
USER_NOT_FOUND = ("USR-404", "User is not found.", "User ID is not correct.")
'''
This can be located under the 'schemas' folder in your project as maybe user.py.
'''
class UserResponse(BaseModel):
id: int = Field(..., example=1, description="Unique identifier of the user")
username: str = Field(..., example="Micheal Alice", description="Username or full name of the user")
'''
This can be located under the routers folder.
'''
@app.get(
"/user/{user_id}",
response_model=ResponseModel[UserResponse],
responses=APIResponse.default()
)
async def get_user(user_id: int = Path(..., description="The ID of the user")):
if user_id == 1:
raise APIException(
error_code=UserException.USER_NOT_FOUND,
http_status_code=404,
)
data = UserResponse(id=user_id, username="John Doe")
return ResponseModel(data=data,
description="User fetched successfully.")From the above AuthException and UserException, which have extended the BaseExceptionCode, the below .yaml file can be generated. It will be both importable and exportable so that it can be shared and/or edited by other teams working in the same project or product owners to decide on what exception should be thrown.
version: 1
defaults:
rfc7807_type_base: "https://example.com/problems" # optional
groups:
auth:
prefix: "AUTH"
items:
AUTH_FAILED:
code: "100"
message: "User is not able to log in."
description: "Password is incorrect."
# rfc7807_type: "authentication-error" # optional
# rfc7807_instance: "/login" # optional
users:
prefix: "USR"
items:
USER_NOT_FOUND:
code: "404"
message: "User is not found."
description: "User ID is not correct."This is going to give us the ability to successfully group the exception cases. Localisation can be added as well. Still, handling the exceptions from the frontend is a better approach, but when it's required to handle the exception messages from the backend or you want to make the backend clean and structured, this approach is legendary.
Metadata
Metadata
Assignees
Labels
Projects
Status