add api exception handler (#74)

* try to add exception handler

* improve server error test

* fix lint

* add build_uri util

* fix header file path

---------

Co-authored-by: Dmitry Afanasyev <afanasiev@litres.ru>
This commit is contained in:
Dmitry Afanasyev
2023-12-30 23:50:59 +03:00
committed by GitHub
parent d1ae7f2281
commit bf7a5520dc
10 changed files with 171 additions and 45 deletions

View File

@@ -0,0 +1,27 @@
from typing import Any
from fastapi import status as status_code
from pydantic import BaseModel, Field
class BaseError(BaseModel):
"""Error response as defined in
https://datatracker.ietf.org/doc/html/rfc7807.
One difference is that the member "type" is not a URI
"""
type: str | None = Field(title="The name of the class of the error")
title: str | None = Field(
title="A short, human-readable summary of the problem that does not change from occurence to occurence",
)
detail: str | None = Field(
default=None, title="А human-readable explanation specific to this occurrence of the problem"
)
instance: Any | None = Field(default=None, title="Identifier for this specific occurrence of the problem")
class BaseResponse(BaseModel):
status: int = Field(..., title="Status code of request.", example=status_code.HTTP_200_OK) # type: ignore[call-arg]
error: dict[Any, Any] | BaseError | None = Field(default=None, title="Errors")
payload: Any | None = Field(default_factory=dict, title="Payload data.")

View File

@@ -1,2 +1,34 @@
from fastapi.responses import ORJSONResponse
from starlette.requests import Request
from api.base_schemas import BaseError, BaseResponse
class BaseAPIException(Exception):
pass
class InternalServerError(BaseError):
pass
class InternalServerErrorResponse(BaseResponse):
error: InternalServerError
class Config:
json_schema_extra = {
"example": {
"status": 500,
"error": {
"type": "InternalServerError",
"title": "Server encountered an unexpected error that prevented it from fulfilling the request",
"detail": "error when adding send message",
},
},
}
async def internal_server_error_handler(_request: Request, _exception: Exception) -> ORJSONResponse:
error = InternalServerError(title="Something went wrong!", type="InternalServerError")
response = InternalServerErrorResponse(status=500, error=error).model_dump(exclude_unset=True)
return ORJSONResponse(status_code=500, content=response)