首页 > 编程问答 >如何在 FastAPI 中间件中以不同方式捕获或处理 RequestValidationError 异常?

如何在 FastAPI 中间件中以不同方式捕获或处理 RequestValidationError 异常?

时间:2024-07-28 13:28:49浏览次数:17  
标签:python exception fastapi middleware fastapi-middleware

如何正确组合 RequestValidationError 异常处理程序,如:

@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
    response = prepare_response({}, g_ERROR__INCORRECT_PARAMS)

    return JSONResponse(content=response)

和中间件函数,如:

@app.middleware("http")
async def response_middleware(request: Request, call_next):
    try:
        result = await call_next(request)

        res_body = b''
        async for chunk in result.body_iterator:
            res_body += chunk

        response = prepare_response(res_body.decode(), g_ERROR__ALL_OK)
    except Exception as e:
        response = prepare_response({}, g_ERROR__UNKNOWN_ERROR)

    return JSONResponse(content=response)

必须 只有 异常才触发以下函数:|| |而,在所有其他情况下,应该触发以下函数: RequestValidationError 现在,

@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):

函数一直触发并处理

@app.middleware("http")
async def response_middleware(request: Request, call_next):

的结果,这违反了函数的基本意图。 response_middleware 当使用 validation_exception_handler 时,任何异常都会消失,即使没有

,代码也会一致地生成 @app.middleware("http") 响应,并且以下内容: @app.exception_handler(RequestValidationError) 在以下代码行之后也根本不起作用: 200 OK 没有异常

    try:
        result = await call_next(request)

        res_body = b''
        async for chunk in result.body_iterator:
            res_body += chunk

        response = prepare_response(res_body.decode(), g_ERROR__ALL_OK)
    except RequestValidationError as e:
        response = prepare_response({}, g_ERROR__INCORRECT_PARAMS)
    except Exception as e:
        response = prepare_response({}, g_ERROR__UNKNOWN_ERROR)

这个问题怎么解决?

result = await call_next(request)

一方面我们需要不同功能的中间件代码,另一方面需要在中间代码之前跟踪一些异常(参数不正确等)或在其中,但不更深。

How can this problem be solved?

On the one hand, we need middleware code for different functions, and on the other hand, some exceptions (incorrect parameters, etc.) should be tracked before the intermediate code or inside it, but not deeper.


The issue you're facing arises because your middleware is catching all exceptions, including RequestValidationError , preventing your custom exception handler from being triggered.

Here's how to solve this and achieve the desired behavior:

1. Modify your middleware to re-raise RequestValidationError :

@app.middleware("http")
async def response_middleware(request: Request, call_next):
    try:
        result = await call_next(request)

        res_body = b''
        async for chunk in result.body_iterator:
            res_body += chunk

        response = prepare_response(res_body.decode(), g_ERROR__ALL_OK)
    except RequestValidationError as e:
        # Re-raise the exception to be handled by the exception handler
        raise e
    except Exception as e:
        response = prepare_response({}, g_ERROR__UNKNOWN_ERROR)

    return JSONResponse(content=response)

By re-raising the RequestValidationError , you allow it to propagate up to the dedicated exception handler.

2. Ensure your exception handler returns a Response object:

@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
    response = prepare_response({}, g_ERROR__INCORRECT_PARAMS)
    return JSONResponse(content=response, status_code=422)  # Return a Response with appropriate status code

Make sure your exception handler returns a Response object, ideally with a status code like 422 Unprocessable Entity for validation errors. This response will be sent to the client.

Explanation:

  • Middleware's Role: Your middleware is designed to handle successful responses and general exceptions. It shouldn't handle validation errors directly.
  • Exception Handler's Purpose: The exception handler is specifically designed to handle RequestValidationError instances, providing customized responses for these cases.
  • Re-raising the Exception: By re-raising RequestValidationError within the middleware's try...except block, you ensure that the exception isn't suppressed and can be caught by the designated exception handler.

With these modifications:

  • Successful requests will be processed by the middleware and returned with a g_ERROR__ALL_OK response.
  • RequestValidationError exceptions will be caught by the middleware, re-raised, and then handled by the validation_exception_handler , returning a g_ERROR__INCORRECT_PARAMS response.
  • Other exceptions will be caught and handled by the middleware's generic exception handling, returning a g_ERROR__UNKNOWN_ERROR response.

This approach maintains a clear separation of concerns: middleware for general response handling and exception handling for specific error types.

标签:python,exception,fastapi,middleware,fastapi-middleware
From: 77616388

相关文章

  • 在 FastAPI + JWT 身份验证中如何最好地实现 is_active ?
    我的用户模型有一个字段is_active。如果为假,则说明该用户的账户被封锁。在这种情况下如何实施访问限制?我应该拒绝用户访问某些端点吗?执行此检查的最佳地点在哪里?如果is_active=False,它是否应该在get_current_user依赖项中?我的依赖项函数get_current_userasyncdefg......
  • AttributeError:'int'对象没有属性'index'(python)
    我正在Python上进行“猜单词”,但我无法弄清楚这个错误。AttributeError:'int'objecthasnoattribute'index'(python)它在线上给了我一个错误letterIndex=word.index(guess)defcheckLetter(word):blanks='_'*len(str(word))print('W......
  • 尝试在Python中使用for循环来输出大于或等于序列中的数字
    这是我的Python代码:largest_so_far=-1print('before',largest_so_far)forthe_numin[9,41,12,3,74,15]:ifthe_num>largest_so_far:largest_so_far=the_numprint(largest_so_far,'isbiggerthan',the_num)......
  • 如何在 wxPython 的 for 循环中添加文本输入框?
    我是wxPython的新手,正在开发一个带有GUI的基本程序,让用户标记图像。现在,当用户单击“导入”按钮时,他们可以选择一个目录。然后,代码使用matplotlib在for循环中显示该目录中的每个图像。但是,我不知道如何在for循环中访问用户输入。这就是该函数现在的样子:importmatplo......
  • 【Python】字母 Rangoli 图案
    一、题目YouaregivenanintegerN.YourtaskistoprintanalphabetrangoliofsizeN.(RangoliisaformofIndianfolkartbasedoncreationofpatterns.)Differentsizesofalphabetrangoliareshownbelow:#size3----c------c-b-c--c-b-a-b-c--c......
  • python 闭包、装饰器
    一、闭包:1.外部函数嵌套内部函数 2.外部函数返回内部函数 3.内部函数可以访问外部函数局部变量         闭包(Closure)是指在一个函数内部定义的函数,并且内部函数可以访问外部函数的局部变量,即使外部函数已经执行完毕,这种现象称为闭包。在Python中,闭包常常用......
  • 掌握 IPython %%time 魔法命令:高效测量代码块执行时间
    引言在编程和数据分析中,了解代码的执行时间是优化性能的关键步骤。IPython,作为一个强大的交互式计算环境,提供了多种工具来帮助用户测量和优化代码。其中,%%time魔法命令是IPython中用来测量代码块执行时间的便捷工具。本文将详细介绍%%time魔法命令的使用方法,并通过一......
  • 探索 IPython 中的 %%javascript 魔法命令:运行 JavaScript 代码的秘籍
    引言IPython是一个强大的交互式计算环境,它不仅支持Python语言,还通过各种魔法命令扩展了其功能。其中,%%javascript魔法命令是IPython扩展中一个非常有趣的特性,它允许用户在IPython环境中直接运行JavaScript代码。这对于需要在数据科学和科学计算中使用JavaScript......
  • pythonasm库分析,看看你和自学编程小学生的差距
    下面是pythonasm.asm库的源代码fromkeystoneimport*fromcapstoneimport*assembly_instructions=[]#储存汇编指令的列表#汇编指令写入列表defmov(reg1,reg2):assembly_instructions.append(f"mov{reg1},{reg2}")defdb(value):assembly_instructio......
  • 【Python系列】Python 中的垃圾收集:深入理解与实践
    ......