From 6989219c33b3381b737ce828b3c088f0575523ef Mon Sep 17 00:00:00 2001 From: Nikita Tikhonov Date: Tue, 27 Feb 2024 13:10:01 +0300 Subject: [PATCH] Handle validation errors. --- melody/kit/core.py | 9 +++++++++ melody/kit/errors/core.py | 14 ++++++++++++++ pyproject.toml | 4 ++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/melody/kit/core.py b/melody/kit/core.py index 54c6810..2c5fdb1 100644 --- a/melody/kit/core.py +++ b/melody/kit/core.py @@ -1,6 +1,7 @@ from argon2 import PasswordHasher from authlib.integrations.starlette_client import OAuth # type: ignore[import-untyped] from fastapi.applications import FastAPI +from fastapi.exceptions import RequestValidationError from fastapi.middleware.cors import CORSMiddleware from fastapi.requests import Request from fastapi.responses import JSONResponse @@ -95,6 +96,14 @@ async def http_error_handler(request: Request, error: HTTPError) -> JSONResponse return await error_handler(request, converted_error) + @app.exception_handler(RequestValidationError) + async def validation_error_handler( + request: Request, error: RequestValidationError + ) -> JSONResponse: + converted_error = Error.from_validation_error(error) + + return await error_handler(request, converted_error) + @app.exception_handler(NormalError) async def normal_error_handler(request: Request, error: NormalError) -> JSONResponse: internal_error = InternalError() diff --git a/melody/kit/errors/core.py b/melody/kit/errors/core.py index 62386db..42696f7 100644 --- a/melody/kit/errors/core.py +++ b/melody/kit/errors/core.py @@ -3,6 +3,8 @@ from enum import Enum from typing import ClassVar, Optional, Type +from fastapi import status +from fastapi.exceptions import RequestValidationError from starlette.exceptions import HTTPException as HTTPError from typing_aliases import NormalError from typing_extensions import Self @@ -12,6 +14,8 @@ __all__ = ("ErrorCode", "Error", "ErrorData", "ErrorType") +VALIDATION_ERROR = "validation error" + class ErrorCode(Enum): BASE = 10000 @@ -180,5 +184,15 @@ def from_http_error(cls, error: HTTPError) -> Self: return cls(message, code, status_code) + @classmethod + def from_validation_error(cls, error: RequestValidationError) -> Self: + message = VALIDATION_ERROR + + status_code = status.HTTP_422_UNPROCESSABLE_ENTITY + + code = ErrorCode.from_status_code(status_code) + + return cls(message, code, status_code) + ErrorType = Type[Error] diff --git a/pyproject.toml b/pyproject.toml index 339fc68..102e781 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,7 +30,7 @@ include = "melody" [tool.poetry.scripts] "melody.bot" = "melody.bot.main:bot" "melody.kit" = "melody.kit.main:run" -"melody.web" = "melody.web.main:web" +"melody.web" = "melody.web.main:run" [tool.poetry.dependencies] # melody @@ -146,5 +146,5 @@ wrap_size = 100 display = ["feature", "change", "fix", "security", "deprecation", "removal", "internal"] [build-system] -requires = ["poetry-core >= 1.8.1"] +requires = ["poetry-core >= 1.9.0"] build-backend = "poetry.core.masonry.api"