如何处理aiohttp处理其他异常时的异常?优化JSON文件接收逻辑
处理aiohttp服务器的请求类型校验与异常捕获
我来帮你一步步解决这两个问题——先调整请求类型校验以支持JSON和gzip压缩的JSON,再处理aiohttp的异常捕获。
一、调整请求校验,仅接受JSON或gzip压缩的JSON
你的现有代码只校验了application/json和multipart/form-data,但我们需要修改逻辑,只允许纯JSON或gzip压缩的JSON请求。这里要注意两种常见的gzip压缩JSON的请求格式:
- 请求头
Content-Type: application/json+Content-Encoding: gzip - 请求头
Content-Type: application/gzip(此时请求体是压缩后的JSON文件)
下面是修改后的代码,包含解压逻辑和类型校验:
import gzip import json from aiohttp import web from aiohttp.web import View, json_response class Uploader(View): async def post(self): # 先检查是否能读取请求体 if not self.request.can_read_body: return json_response({'message': 'Cannot read request body'}, status=400) content_type = self.request.content_type content_encoding = self.request.headers.get('Content-Encoding', '').lower() raw_body = await self.request.read() json_body = None try: # 处理gzip压缩的情况 if content_encoding == 'gzip' or content_type == 'application/gzip': # 解压请求体 try: raw_body = gzip.decompress(raw_body) except gzip.BadGzipFile: return json_response({'message': 'Invalid gzip压缩内容'}, status=400) # 解压后强制校验是否为JSON content_type = 'application/json' # 校验最终的内容类型是否为JSON if content_type != 'application/json': return json_response( {'message': '仅接受JSON或gzip压缩的JSON请求'}, status=415 ) # 解析JSON json_body = json.loads(raw_body) # 处理各类解析异常 except json.JSONDecodeError: return json_response({'message': 'JSON格式无效'}, status=400) # 这里写你处理JSON请求体的业务逻辑 return json_response({'message': '请求处理成功', 'data': json_body}, status=200)
二、处理aiohttp服务器端的异常
在aiohttp中,服务器端常见的异常包括请求体读取异常、HTTP协议异常、自定义业务异常等。我们可以通过两种方式处理:
1. 在视图方法内捕获局部异常
像上面的代码一样,在post方法中用try-except捕获特定异常,比如:
gzip.BadGzipFile:处理无效的gzip压缩包json.JSONDecodeError:处理JSON解析失败aiohttp.web.HTTPException:aiohttp内置的HTTP异常(比如HTTPBadRequest等)
2. 全局异常中间件
如果希望统一处理所有路由的异常,可以添加全局中间件,这样不用在每个视图里重复写异常捕获逻辑:
@web.middleware async def error_middleware(request, handler): try: return await handler(request) except web.HTTPException as ex: # 处理aiohttp内置的HTTP异常,返回统一格式的JSON响应 return json_response({'message': ex.reason}, status=ex.status) except Exception as ex: # 处理其他未知异常,返回500错误 return json_response({'message': f'服务器内部错误: {str(ex)}'}, status=500) # 注册中间件到app app = web.Application(middlewares=[error_middleware]) app.add_routes([web.post('/upload', Uploader)])
这样,无论是视图内抛出的异常,还是aiohttp底层的异常,都会被中间件捕获并返回统一格式的JSON响应,避免返回默认的HTML错误页面。
内容的提问来源于stack exchange,提问作者Nathan Whittle
相关产品推荐
相关产品推荐

