Django Channels部署IIS后WebSocket路由找不到:1006错误排查
Django Channels部署IIS后WebSocket无法连接问题
问题现象
- 本地通过
python runserver运行时,WebSocket连接完全正常:
后端日志显示:new WebSocket('ws://127.0.0.1:8000/ws/notificacoes') // 成功建立连接WebSocket HANDSHAKING /ws/notificacoes [127.0.0.1:53541] WebSocket CONNECT /ws/notificacoes [127.0.0.1:53541] - 通过IIS访问时,WebSocket连接直接失败:
后端日志报错:new WebSocket('ws://server:8000/ws/notificacoes') // 触发错误1006ValueError: No route found for path 'ws/notificacoes'
相关代码文件
consumers.py
class NotificacaoConsumer(AsyncWebsocketConsumer): async def connect(self): self.room_group_name = 'notificacoes' await self.channel_layer.group_add( self.room_group_name, self.channel_name ) await self.accept() async def disconnect(self, close_code): await self.channel_layer.group_discard( self.room_group_name, self.channel_name ) async def notificacao_update(self, event): await self.send(text_data=json.dumps({ 'message': 'Notificação atualizada!' }))
routing.py
websocket_urlpatterns = [ ... path('ws/notificacoes', NotificacaoConsumer.as_asgi(), name='notificacao'), ]
asgi.py
from index.routing import websocket_urlpatterns os.environ.setdefault("DJANGO_SETTINGS_MODULE", "web.settings") django_asgi_app = get_asgi_application() application = ProtocolTypeRouter( { "http": django_asgi_app, "websocket": AllowedHostsOriginValidator( AuthMiddlewareStack(URLRouter(websocket_urlpatterns)) ), } )
IIS反向代理配置(web.config)
Daphne运行在8002端口,当前配置如下:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <appSettings> <add key="WSGI_HANDLER" value="django.core.wsgi.get_wsgi_application()" /> <add key="PYTHONPATH" value="" /> <add key="DJANGO_SETTINGS_MODULE" value="web.settings" /> <add key="WSGI_LOG" value="logs\wfastcgi.log" /> </appSettings> <system.webServer> <httpErrors errorMode="Detailed" /> <handlers> <remove name="WebDAV" /> <remove name="ExtensionlessUrlHandler-Integrated-4.0" /> <add name="Django Handler" path="*" verb="*" modules="FastCgiModule" scriptProcessor="C:\Python\python.exe|C:\Python\Lib\site-packages\wfastcgi.py" resourceType="Unspecified" requireAccess="Script" /> <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,DELETE" type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" responseBufferLimit="0" /> </handlers> <modules> <remove name="WebDAVModule" /> </modules> <tracing> <traceFailedRequests> <add path="*"> <traceAreas> <add provider="ASP" verbosity="Verbose" /> <add provider="ASPNET" areas="Infrastructure,Module,Page,AppServices" verbosity="Verbose" /> <add provider="ISAPI Extension" verbosity="Verbose" /> <add provider="WWW Server" areas="Authentication,Security,Filter,StaticFile,CGI,Compression,Cache,RequestNotifications,Module,FastCGI,WebSocket" verbosity="Verbose" /> </traceAreas> <failureDefinitions statusCodes="500" verbosity="Warning" /> </add> </traceFailedRequests> </tracing> <httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="*" /> </customHeaders> </httpProtocol> <rewrite> <rules> <!-- Reverse proxy for Daphne running on 8002 --> <rule name="WebSocket Proxy" patternSyntax="Wildcard" stopProcessing="true"> <match url="ws*" /> <conditions> <add input="{HTTP_CONNECT}" pattern="*" /> </conditions> <action type="Rewrite" url="http://localhost:8002/{R:0}" logRewrittenUrl="true" /> <serverVariables> <set name="HTTP_SEC_WEBSOCKET_EXTENSIONS" value="" /> </serverVariables> </rule> </rules> </rewrite> </system.webServer> </configuration>
解决方案
1. 修复反向代理规则的匹配逻辑
当前规则里的<add input="{HTTP_CONNECT}" pattern="*" />仅匹配CONNECT请求,但WebSocket握手使用的是GET请求,导致规则完全不触发——WebSocket请求被WSGI接管,自然找不到对应路由。
修改web.config中的反向代理规则:
<rule name="WebSocket Proxy" stopProcessing="true"> <match url="ws/(.*)" /> <conditions> <add input="{HTTP_UPGRADE}" pattern="websocket" /> <add input="{HTTP_CONNECTION}" pattern="upgrade" /> </conditions> <action type="Rewrite" url="http://localhost:8002/{R:0}" logRewrittenUrl="true" /> <serverVariables> <set name="HTTP_SEC_WEBSOCKET_EXTENSIONS" value="" /> </serverVariables> </rule>
- 用
HTTP_UPGRADE和HTTP_CONNECTION这两个标准头识别WebSocket握手请求 - 匹配URL改为
ws/(.*),更精准锁定WebSocket路径
2. 确保Daphne正确监听
启动Daphne时绑定到0.0.0.0(允许所有IP访问),而非仅本地:
daphne -b 0.0.0.0 -p 8002 web.asgi:application
3. 统一路径的斜杠规则
routing.py中添加路径末尾的斜杠:
path('ws/notificacoes/', NotificacaoConsumer.as_asgi(), name='notificacao'),
前端连接同步改为:
new WebSocket('ws://server:8000/ws/notificacoes/')
避免Django路径匹配的歧义问题
4. 启用IIS的WebSocket组件
打开服务器管理器 -> 添加角色和功能 -> Web服务器(IIS) -> 应用程序开发 -> 勾选WebSocket协议,安装后重启IIS
5. 检查AllowedHosts配置
确保settings.py的ALLOWED_HOSTS包含服务器域名/IP:
ALLOWED_HOSTS = ['server', 'localhost', '127.0.0.1']
否则AllowedHostsOriginValidator会直接拒绝连接
验证步骤
- 重启IIS和Daphne服务
- 发起WebSocket连接,查看Daphne日志是否出现
HANDSHAKING和CONNECT记录 - 若仍报错,查看IIS失败请求日志,确认请求是否正确转发到Daphne
内容的提问来源于stack exchange,提问作者Gustavo Lisi
相关产品推荐
相关产品推荐

