在 heroku 上托管 ASGI 时出现 "Django can only handle ASGI/HTTP connections, not websocket." 错误?
Getting a "Django can only handle ASGI/HTTP connections, not websocket." error when hosting ASGI on heroku?
浏览 Whosebug 和 Youtube 上的每个问题以寻找答案。我正在通过 Heroku 上的 Django 频道部署 WSGI 和 ASGI/websockets。它在本地工作,但在生产过程中一直给我带来麻烦。
设置
这是我的过程文件:
web: daphne API.asgi:application --port $PORT --bind 0.0.0.0 -v2
worker: python manage.py runworker background -v2
Settings.py:
# Redis Setup
ASGI_APPLICATION = 'API.routing.application'
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [(HEROKU_URL, 6379)],
},
},
}
asgi.py:
import os
import django
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'API.settings')
django.setup()
application = get_asgi_application()
最后,routing.py:
application = ProtocolTypeRouter({
'websocket':AllowedHostsOriginValidator(
AuthMiddlewareStack(
URLRouter(
[
url(r"^timer/$", TestConsumer.as_asgi()),
]
)
)
)
,'channel':ChannelNameRouter({
'background':BackgroundConsumer.as_asgi()
})
})
Problem/logs
连接到 websocket 时 Heroku 记录:
2021-07-02T19:42:42.209398+00:00 app[web.1]: IP - - [02/Jul/2021:19:42:42] "GET /chat_switch/1/" 200 10480
2021-07-02T19:43:02.708851+00:00 app[web.1]: IP - - [02/Jul/2021:19:43:02] "WSCONNECTING /timer/" - -
2021-07-02T19:43:02.709658+00:00 app[web.1]: 2021-07-02 19:43:02,709 DEBUG Upgraded connection [IP, 32183] to WebSocket
2021-07-02T19:43:03.058159+00:00 app[web.1]: 2021-07-02 19:43:03,057 ERROR Exception inside application: Django can only handle ASGI/HTTP connections, not websocket.
2021-07-02T19:43:03.058167+00:00 app[web.1]: Traceback (most recent call last):
2021-07-02T19:43:03.058168+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.8/site-packages/django/core/handlers/asgi.py", line 143, in __call__
2021-07-02T19:43:03.058168+00:00 app[web.1]: raise ValueError(
2021-07-02T19:43:03.058169+00:00 app[web.1]: ValueError: Django can only handle ASGI/HTTP connections, not websocket.
2021-07-02T19:43:03.059813+00:00 app[web.1]: 2021-07-02 19:43:03,059 INFO failing WebSocket opening handshake ('Internal server error')
2021-07-02T19:43:03.060494+00:00 app[web.1]: 2021-07-02 19:43:03,060 WARNING dropping connection to peer tcp4:IP:32183 with abort=False: Internal server error
2021-07-02T19:43:03.064484+00:00 app[web.1]: 2021-07-02 19:43:03,063 DEBUG WebSocket closed for [IP, 32183]
除此之外,常规 API 函数按预期工作。
我试过的
- 将 procfile 更改为此处的答案:Websockets with Django Channels on Heroku(无效)
- 将 asgi.py 更改为此处的答案:(输出无差异)
- 在
settings.py
中修改了 Redis URL
- 考虑转行
如果有人知道我可以从这里做什么,我将不胜感激。
routing.py
中的 application
似乎没有做任何事情。我看到它在 ASGI_APPLICATION
中指定,但我相信,它被开发服务器使用 (manage.py runserver
)。在您的 daphne
命令中,您正在服务 API.asgi:application
,它只定义了 django ASGI 应用程序——“http”连接处理程序。
您需要将 get_asgi_application()
替换为 ProtocolTypeRouter
,它定义了每个协议的服务方式 - “http”转到 django ASGI 应用程序,“websocket”转到您的消费者路由。
查看频道文档中的 Deploying 部分。您的 asgi.py
可能看起来像这样(我没有包括您的消费者进口商品):
import os
from django.core.asgi import get_asgi_application
from django.urls import path
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'API.settings')
django_asgi_app = get_asgi_application()
from channels.auth import AuthMiddlewareStack
from channels.security.websocket import AllowedHostsOriginValidator
from channels.routing import ProtocolTypeRouter, URLRouter, ChannelNameRouter
application = ProtocolTypeRouter({
'http': django_asgi_app,
'websocket': AllowedHostsOriginValidator(
AuthMiddlewareStack(
URLRouter(
[
path('timer/', TestConsumer.as_asgi()),
]
)
)
),
'channel': ChannelNameRouter({
'background': BackgroundConsumer.as_asgi()
})
})
浏览 Whosebug 和 Youtube 上的每个问题以寻找答案。我正在通过 Heroku 上的 Django 频道部署 WSGI 和 ASGI/websockets。它在本地工作,但在生产过程中一直给我带来麻烦。
设置
这是我的过程文件:
web: daphne API.asgi:application --port $PORT --bind 0.0.0.0 -v2
worker: python manage.py runworker background -v2
Settings.py:
# Redis Setup
ASGI_APPLICATION = 'API.routing.application'
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [(HEROKU_URL, 6379)],
},
},
}
asgi.py:
import os
import django
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'API.settings')
django.setup()
application = get_asgi_application()
最后,routing.py:
application = ProtocolTypeRouter({
'websocket':AllowedHostsOriginValidator(
AuthMiddlewareStack(
URLRouter(
[
url(r"^timer/$", TestConsumer.as_asgi()),
]
)
)
)
,'channel':ChannelNameRouter({
'background':BackgroundConsumer.as_asgi()
})
})
Problem/logs
连接到 websocket 时 Heroku 记录:
2021-07-02T19:42:42.209398+00:00 app[web.1]: IP - - [02/Jul/2021:19:42:42] "GET /chat_switch/1/" 200 10480
2021-07-02T19:43:02.708851+00:00 app[web.1]: IP - - [02/Jul/2021:19:43:02] "WSCONNECTING /timer/" - -
2021-07-02T19:43:02.709658+00:00 app[web.1]: 2021-07-02 19:43:02,709 DEBUG Upgraded connection [IP, 32183] to WebSocket
2021-07-02T19:43:03.058159+00:00 app[web.1]: 2021-07-02 19:43:03,057 ERROR Exception inside application: Django can only handle ASGI/HTTP connections, not websocket.
2021-07-02T19:43:03.058167+00:00 app[web.1]: Traceback (most recent call last):
2021-07-02T19:43:03.058168+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.8/site-packages/django/core/handlers/asgi.py", line 143, in __call__
2021-07-02T19:43:03.058168+00:00 app[web.1]: raise ValueError(
2021-07-02T19:43:03.058169+00:00 app[web.1]: ValueError: Django can only handle ASGI/HTTP connections, not websocket.
2021-07-02T19:43:03.059813+00:00 app[web.1]: 2021-07-02 19:43:03,059 INFO failing WebSocket opening handshake ('Internal server error')
2021-07-02T19:43:03.060494+00:00 app[web.1]: 2021-07-02 19:43:03,060 WARNING dropping connection to peer tcp4:IP:32183 with abort=False: Internal server error
2021-07-02T19:43:03.064484+00:00 app[web.1]: 2021-07-02 19:43:03,063 DEBUG WebSocket closed for [IP, 32183]
除此之外,常规 API 函数按预期工作。
我试过的
- 将 procfile 更改为此处的答案:Websockets with Django Channels on Heroku(无效)
- 将 asgi.py 更改为此处的答案:(输出无差异)
- 在
settings.py
中修改了 Redis URL
- 考虑转行
如果有人知道我可以从这里做什么,我将不胜感激。
routing.py
中的 application
似乎没有做任何事情。我看到它在 ASGI_APPLICATION
中指定,但我相信,它被开发服务器使用 (manage.py runserver
)。在您的 daphne
命令中,您正在服务 API.asgi:application
,它只定义了 django ASGI 应用程序——“http”连接处理程序。
您需要将 get_asgi_application()
替换为 ProtocolTypeRouter
,它定义了每个协议的服务方式 - “http”转到 django ASGI 应用程序,“websocket”转到您的消费者路由。
查看频道文档中的 Deploying 部分。您的 asgi.py
可能看起来像这样(我没有包括您的消费者进口商品):
import os
from django.core.asgi import get_asgi_application
from django.urls import path
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'API.settings')
django_asgi_app = get_asgi_application()
from channels.auth import AuthMiddlewareStack
from channels.security.websocket import AllowedHostsOriginValidator
from channels.routing import ProtocolTypeRouter, URLRouter, ChannelNameRouter
application = ProtocolTypeRouter({
'http': django_asgi_app,
'websocket': AllowedHostsOriginValidator(
AuthMiddlewareStack(
URLRouter(
[
path('timer/', TestConsumer.as_asgi()),
]
)
)
),
'channel': ChannelNameRouter({
'background': BackgroundConsumer.as_asgi()
})
})