You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何处理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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:47:20