async def validation_exception_handler( request: Request, exc: RequestValidationError) -> UJSONResponse: """ Handles ValidationError, translating it into flat dict error data: * code - unique code of the error in the system * detail - general description of the error * fields - list of dicts with description of the error in each field :param request: Starlette Request instance :param exc: StarletteHTTPException instance :return: UJSONResponse with newly formatted error data """ status_code = getattr(exc, "status_code", 400) headers = getattr(exc, "headers", None) fields = raw_errors_to_fields(exc.raw_errors) if fields: error_codes = set(list(map(lambda x: x["error_code"], fields))) else: error_codes = [getattr(exc, "error_code", status_code)] message = getattr(exc, "message", "Validation error.") if message and not any( [message.endswith("."), message.endswith("?"), message.endswith("!")]): message = message + "." # pragma: no cover data = {"error_codes": error_codes, "message": message, "fields": fields} return UJSONResponse(data, status_code=status_code, headers=headers)
async def validation_exception_handler(request: Request, exc: ValidationError) -> UJSONResponse: """ Handles ValidationError, translating it into flat dict error data: * code - unique code of the error in the system * detail - general description of the error * fields - list of dicts with description of the error in each field :param request: Starlette Request instance :param exc: StarletteHTTPException instance :return: UJSONResponse with newly formatted error data """ # First, let's determine if the body is empty, since we wouldn't be able # to correctly recognize that from the exception (which would tell us about # missing fields even in the case we have 1 pydantic model to parse request # fields as one object (serializer, for example). body = await request.body() if not body: status_code = 400 data = { "code": status_code, "detail": "Empty body for this request is not valid.", "fields": [], } else: fields = raw_errors_to_fields(exc.raw_errors) status_code = getattr(exc, "status_code", 400) data = { "code": getattr(exc, "error_code", status_code), "detail": getattr(exc, "message", "Validation error"), "fields": fields, } return UJSONResponse(data, status_code=status_code)
async def http_exception_handler(request: Request, exc: StarletteHTTPException) -> UJSONResponse: """ Handles StarletteHTTPException, translating it into flat dict error data: * code - unique code of the error in the system * detail - general description of the error * fields - list of dicts with description of the error in each field :param request: Starlette Request instance :param exc: StarletteHTTPException instance :return: UJSONResponse with newly formatted error data """ fields = getattr(exc, "fields", []) message = getattr(exc, "detail", "Validation error.") headers = getattr(exc, "headers", None) if message and not any( [message.endswith("."), message.endswith("?"), message.endswith("!")]): message = message + "." data = { "error_codes": [getattr(exc, "error_code", exc.status_code)], "message": message, "fields": fields, } return UJSONResponse(data, status_code=exc.status_code, headers=headers)
async def internal_server_error_handler( request: Request, exc: RequestValidationError) -> UJSONResponse: code = getattr(exc, "error_code", 500) detail = getattr(exc, "detail", "Internal Server Error.") fields = getattr(exc, "fields", []) status_code = getattr(exc, "status_code", 500) data = {"error_codes": [code], "message": detail, "fields": fields} return UJSONResponse(data, status_code=status_code)
async def not_found_error_handler( request: Request, exc: RequestValidationError) -> UJSONResponse: code = getattr(exc, "error_code", 404) detail = getattr(exc, "detail", "Not found.") fields = getattr(exc, "fields", []) status_code = getattr(exc, "status_code", 404) data = {"error_codes": [code], "message": detail, "fields": fields} return UJSONResponse(data, status_code=status_code)
async def custom_route_handler(request: Request) -> Response: try: return await original_route_handler(request) except RequestValidationError as exc: body = await request.body() if not body: status_code = 400 data = { "code": status_code, "detail": "Empty body for this request is not valid.", "fields": [], } return UJSONResponse(data, status_code=status_code) else: raise exc
def default_on_error( conn: HTTPConnection, exc: Exception ) -> UJSONResponse: """ Overriden method just to make sure we return response in our format. :param conn: HTTPConnection of the current request-response cycle :param exc: Any exception that could have been raised :return: UJSONResponse with error data as dict and 403 status code """ return UJSONResponse( {"code": 403, "detail": "Forbidden.", "fields": []}, status_code=403, )
async def http_exception_handler(request: Request, exc: StarletteHTTPException) -> UJSONResponse: """ Handles StarletteHTTPException, translating it into flat dict error data: * code - unique code of the error in the system * detail - general description of the error * fields - list of dicts with description of the error in each field :param request: Starlette Request instance :param exc: StarletteHTTPException instance :return: UJSONResponse with newly formatted error data """ fields = getattr(exc, "fields", []) data = { "code": getattr(exc, "error_code", exc.status_code), "detail": getattr(exc, "message", exc.detail), "fields": fields, } return UJSONResponse(data, status_code=exc.status_code)
async def validation_exception_handler( request: Request, exc: RequestValidationError) -> UJSONResponse: """ Handles ValidationError, translating it into flat dict error data: * code - unique code of the error in the system * detail - general description of the error * fields - list of dicts with description of the error in each field :param request: Starlette Request instance :param exc: StarletteHTTPException instance :return: UJSONResponse with newly formatted error data """ fields = raw_errors_to_fields(exc.raw_errors) status_code = getattr(exc, "status_code", 400) data = { "code": getattr(exc, "error_code", status_code), "detail": getattr(exc, "message", "Validation error"), "fields": fields, } return UJSONResponse(data, status_code=status_code)
def test_ujson_response_helps_with_slashes(): url = "http://hello.world/endpoint/?key=value" json = UJSONResponse().render(content={"url": url}) assert json == f'{{"url":"{url}"}}'.encode('utf-8')