Django升级至3.2.8后结合Channels与OpenCensus中间件出现500错误:TypeError: object HttpResponse can't be used in 'await' expression
搞定Django 3.2 + Channels + OpenCensus中间件触发的500错误
先拆解问题根源
从你贴的错误日志里,两个核心异常已经把问题点得明明白白了:
AttributeError: 'coroutine' object has no attribute 'get':Clickjacking中间件想调用response.get()来处理X-Frame-Options头,但此时的response居然是个协程对象,不是正常的HttpResponseTypeError: object HttpResponse can't be used in 'await' expression:ASGI的异步处理链在等待一个协程结果,却拿到了同步的HttpResponse对象
本质原因就是同步实现的OpenCensus中间件,在Django 3.2的ASGI异步处理流程中水土不服。Django 3.2对ASGI的中间件执行逻辑做了优化,当用Channels当ASGI服务器时,HTTP请求走的是异步处理链,而同步中间件没做适配的话,会直接打乱响应的类型流转,导致后续环节拿到完全不符合预期的对象。
给你几个可行的解决方案
方案1:把OpenCensus中间件包装成异步兼容版
Django自带的SyncToAsync工具可以帮我们把同步中间件转换成异步兼容的。你可以这么做:
- 在项目根目录新建一个
middleware.py文件,写个包装器:
from asgiref.sync import SyncToAsync from opencensus.ext.django.middleware import OpencensusMiddleware class AsyncOpencensusMiddleware: def __init__(self, get_response): self.sync_middleware = OpencensusMiddleware(get_response) self.get_response = get_response async def __call__(self, request): # 把同步的请求前置处理转成异步执行 await SyncToAsync(self.sync_middleware.process_request)(request) # 继续走后续中间件/视图的异步流程 response = await self.get_response(request) # 把同步的响应后置处理转成异步执行 response = await SyncToAsync(self.sync_middleware.process_response)(request, response) return response
- 然后修改
settings.py里的MIDDLEWARE列表,把原来的OpenCensus中间件替换成我们写的异步版本:
MIDDLEWARE = [ # ... 其他中间件保持不动 'testproject.middleware.AsyncOpencensusMiddleware' # 这里换成你项目的实际路径 ]
方案2:调整ASGI配置,给HTTP请求加同步适配包装
你也可以直接修改asgi.py,给Django的ASGI应用套一层SyncToAsync,确保同步中间件能正常工作:
import os from django.core.asgi import get_asgi_application from asgiref.sync import SyncToAsync from channels.auth import AuthMiddlewareStack from channels.routing import ProtocolTypeRouter, URLRouter import testproject.routing os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testproject.settings') application = ProtocolTypeRouter({ # 给HTTP请求的ASGI应用加同步适配 "http": SyncToAsync(get_asgi_application()), "websocket": AuthMiddlewareStack( URLRouter( testproject.routing.websocket_urlpatterns ) ), })
方案3:升级OpenCensus到最新版本
有可能是你用的opencensus-ext-django版本太老,没适配Django 3.2的ASGI环境。先试试升级:
pip install --upgrade opencensus-ext-django
如果升级后还是不行,那大概率是OpenCensus的中间件本身存在ASGI兼容性bug,你可以去他们的仓库提交issue,把你的场景(Django3.2+Channels+同步中间件)描述清楚。
验证方法
- 随便选一个方案改完后,重启Daphne服务器
- 访问http://127.0.0.1:8000/,看看是不是能正常返回响应了
- 再看日志,确认之前那两个异常消失了就行
内容的提问来源于stack exchange,提问作者Oscar Hermoso
相关产品推荐
相关产品推荐

