[英]How handle errors on AioHttp using Connexion
I'd like to handle errors using AioHttp and Connexion in my python web apis in the same way Flask does through @app.errorhandler(Exception)
我想在我的 python web apis 中使用 AioHttp 和 Connexion 处理错误,就像 Flask 通过
@app.errorhandler(Exception)
In another words, let's say my services raises SomethingAlreadyExists and I want to return 409 Conflict, rather than add the code below in all my apis:换句话说,假设我的服务引发了 SomeAlreadyExists 并且我想返回 409 Conflict,而不是在我的所有 api 中添加以下代码:
try:
myservice.create_something(..)
except SomethingAlreadyExists as error: # Repeated code -> DRY
return json_response({"message": str(error)}, status=409)
I'd like to just call the myservice.create_something(..)
in the API layer and the error handle would return the 409 for SomethingAlreadyExists
exceptions or 404 for SomethingNotFound
.我只想调用 API 层中的
myservice.create_something(..)
,错误句柄将为SomethingAlreadyExists
异常返回 409 或为SomethingNotFound
返回 404 。
Note: In Flask land it would be something like below:注意:在 Flask 土地上,它将类似于以下内容:
import connexion
def create_api_app(version='api'):
connexion_app = connexion.FlaskApp(__name__, specification_dir='../api/')
connexion_app.add_api('openapi.yaml', validate_responses=True)
app = connexion_app.app
# It intercepts the specific exception and returns the respective status_code
@app.errorhandler(InvalidValueException)
def bad_request_handler(error):
return 'Bad Request: {}'.format(str(error)), 400
@app.errorhandler(NotFoundException)
def not_found_handler(error):
return 'Not found: {}'.format(str(error)), 404
@app.errorhandler(AlreadyExistsException)
def conflict_handler(error):
return 'Conflict: {}'.format(str(error)), 409
# my_service.py
def get_model(i):
model = get_model_or_none(id)
if btask is None:
raise NotFoundException(f"Model id:{id} not found.")
...
# api.py
def get_model(id):
model = my_service.get_model(id)
# handle errors not required ;)
return btask.to_dict()
I'd like to do the same in my AioHttp connexion app:我想在我的 AioHttp 连接应用程序中做同样的事情:
from connexion import AioHttpApp
def create_app():
connexion_app = AioHttpApp(__name__, port=8000, specification_dir="../", only_one_api=True)
connexion_app.add_api("openapi.yaml", pass_context_arg_name="request")
# Do something here.. like
# web.Application(middlewares=[handle_already_exists_errors]) --> doesn't work
# OR
# connex_app.add_error_handler(
# AlreadyExistsException, handle_already_exists_errors) --> doesn't work too
return connexion_app
Cheers and I'll appreciate any help!干杯,我会感谢任何帮助!
Roger罗杰
I was digging into the connexion and aiohttp code and figured out a way to do it using middlewares:我正在深入研究connexion和aiohttp代码,并想出了一种使用中间件来做到这一点的方法:
import json
from aiohttp.web import middleware
from connexion.lifecycle import ConnexionResponse
from connexion import AioHttpApp
from .exceptions import NotFoundException, AlreadyExistsException
def create_app():
connexion_app = AioHttpApp(
__name__, port=8000, specification_dir="../", only_one_api=True
)
connexion_app.add_api("openapi.yaml", pass_context_arg_name="request")
connexion_app.app.middlewares.append(errors_handler_middleware)
return connexion_app
@middleware
async def errors_handler_middleware(request, handler):
""" Handle standard errors returning response following the connexion style messages"""
try:
response = await handler(request)
return response
except NotFoundException as error:
return json_error(message=str(error), title='Not Found', status_code=404)
except AlreadyExistsException as error:
return json_error(message=str(error), title='Conflict', status_code=409)
def json_error(message, title, status_code):
return ConnexionResponse(
body=json.dumps({
'title': title,
'detail': message,
'status': status_code,
}).encode('utf-8'),
status_code=status_code,
content_type='application/json'
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.