еще правки

This commit is contained in:
Raykov-MS 2026-06-16 15:22:39 +03:00
parent 2f5cb21dc0
commit 5210f1d6f7
2 changed files with 38 additions and 0 deletions

View File

@ -1,4 +1,5 @@
from fastapi import FastAPI, HTTPException, status from fastapi import FastAPI, HTTPException, status
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
from sqlalchemy.exc import IntegrityError, OperationalError, SQLAlchemyError, DBAPIError from sqlalchemy.exc import IntegrityError, OperationalError, SQLAlchemyError, DBAPIError
@ -94,7 +95,28 @@ def map_http_exception(exc: HTTPException) -> tuple[int, int, str, str]:
return status_code, status_code, message, "" return status_code, status_code, message, ""
def map_request_validation_error(exc: RequestValidationError) -> tuple[int, int, str, str]:
status_code = status.HTTP_422_UNPROCESSABLE_ENTITY
errors = exc.errors()
if not errors:
return status_code, status_code, "Validation error", ""
first_error = errors[0]
message = str(first_error.get("msg") or "Validation error")
loc = first_error.get("loc") or ()
field = ".".join(str(part) for part in loc if part not in ("body", "query", "path", "header", "cookie"))
return status_code, status_code, message, field
def register_exception_handlers(app: FastAPI) -> None: def register_exception_handlers(app: FastAPI) -> None:
@app.exception_handler(RequestValidationError)
async def request_validation_exception_handler(request, exc: RequestValidationError):
status_code, code, message, field = map_request_validation_error(exc)
return JSONResponse(
status_code=status_code,
content=_error_payload(code, message, field=field),
)
@app.exception_handler(HTTPException) @app.exception_handler(HTTPException)
async def http_exception_handler(request, exc: HTTPException): async def http_exception_handler(request, exc: HTTPException):
status_code, code, message, field = map_http_exception(exc) status_code, code, message, field = map_http_exception(exc)

View File

@ -29,6 +29,10 @@ def _make_app() -> FastAPI:
exc.orig = Exception("budget_form #99 не существует") exc.orig = Exception("budget_form #99 не существует")
raise exc raise exc
@app.get("/form/{form_id}")
async def form_by_id(form_id: int):
return {"form_id": form_id}
return app return app
@ -66,3 +70,15 @@ def test_sqlalchemy_exception_returns_structured_payload():
"field": "", "field": "",
"message": "budget_form #99 не существует", "message": "budget_form #99 не существует",
} }
def test_request_validation_422_returns_structured_payload():
client = TestClient(_make_app())
response = client.get("/form/not-int")
assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY
assert response.json() == {
"code": status.HTTP_422_UNPROCESSABLE_ENTITY,
"field": "form_id",
"message": "Input should be a valid integer, unable to parse string as an integer",
}