From b1ce043f5034ddd51fc5864d5d057c5ff7e23048 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Fri, 15 Apr 2022 14:38:01 -0700 Subject: [PATCH] add logging for validation error --- fastapi_explosion_extras/routing.py | 13 +++++++++-- fastapi_explosion_extras/tests/api.py | 11 +++++++++ fastapi_explosion_extras/tests/test_router.py | 23 +++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/fastapi_explosion_extras/routing.py b/fastapi_explosion_extras/routing.py index c58ead7..e45fc0b 100644 --- a/fastapi_explosion_extras/routing.py +++ b/fastapi_explosion_extras/routing.py @@ -6,7 +6,8 @@ from fastapi import HTTPException, Request, Response, params from fastapi.applications import FastAPI from fastapi.datastructures import Default, DefaultPlaceholder -from fastapi.encoders import DictIntStrAny, SetIntStr +from fastapi.encoders import DictIntStrAny, SetIntStr, jsonable_encoder +from fastapi.exceptions import RequestValidationError from fastapi.responses import JSONResponse from fastapi.routing import APIRoute, APIRouter, APIWebSocketRoute from fastapi.types import DecoratedCallable @@ -53,11 +54,19 @@ async def custom_route_handler(request: Request) -> Response: if self.logger: self.logger.debug(f"route duration: {duration}") self.logger.debug(f"route response: {response}") + # except RequestValidationError as e: + # body = await request.body() + # detail = { + # "errors": e.errors(), + # "body": body.decode(), + # "path_params": jsonable_encoder(request.path_params), + # "query_params": jsonable_encoder(request.query_params), + # } + # raise HTTPException(status_code=422, detail=detail) except error_types as e: # type: ignore if self.logger: self.logger.error("\n".join(traceback.format_tb(e.__traceback__))) self.logger.error(str(e)) - # If the error is one that we want to catch, return a # consistent response with the Error type so it can # be reversed by the PAM SDK diff --git a/fastapi_explosion_extras/tests/api.py b/fastapi_explosion_extras/tests/api.py index 974841b..dff18d0 100644 --- a/fastapi_explosion_extras/tests/api.py +++ b/fastapi_explosion_extras/tests/api.py @@ -10,6 +10,17 @@ def test_route(i: int): return {"i": i} +class SpecError(ValueError): + pass + + +@router.get("/testing_specific", httpize_errors={SpecError: 400}) +def test_route_specific(i: int): + if i < 1: + raise SpecError("Bad Input Data") + return {"i": i} + + if __name__ == "__main__": from fastapi import FastAPI import uvicorn diff --git a/fastapi_explosion_extras/tests/test_router.py b/fastapi_explosion_extras/tests/test_router.py index fac4e17..c3f1d9f 100644 --- a/fastapi_explosion_extras/tests/test_router.py +++ b/fastapi_explosion_extras/tests/test_router.py @@ -1,4 +1,5 @@ import logging +import uuid import pytest from fastapi import APIRouter, FastAPI from fastapi.testclient import TestClient @@ -73,4 +74,26 @@ def test_route(): return "test" assert router.routes[0].logger == logger + + +def test_request_validation_exception(): + app = FastAPI() + app.router = HttpizeErrorsAPIRouter.from_app(app) + app.include_router(api_router) + init_app(app) + + assert isinstance(app.routes[-1], routing.Route) + + client = TestClient(app) + res = client.get("/testing_specific", params={"i": uuid.uuid4()}) + assert res.status_code == 422 + val_error_data = res.json() + assert "errors" in val_error_data + assert "body" in val_error_data + assert "path_params" in val_error_data + assert "query_params" in val_error_data + + client = TestClient(app) + res = client.get("/testing_specific", params={"i": -1}) + assert res.status_code == 400 \ No newline at end of file