如何正确组合
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'stry...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 thevalidation_exception_handler
, returning ag_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