Websocket with Django channels doesn't work, connection failed
Solution 1
I finally fixed the problem and make ws
used under ssl
connection with wss://
.
For those that are facing the same issue.
Note that I use
-
gunicorn
as web server only forhttp
request -
daphne
as web server forws
web socket -
nginx
as reverse proxy
asgi.py
import os
import django
from channels.routing import get_default_application
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
django.setup()
application = get_default_application()
settings.py
ASGI_APPLICATION = "project.routing.application"
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [(os.environ.get('REDIS_HOST', 'localhost'),6379)],
},
},
}
After setting up the asgi
with django, I use supervisorctl
to keep daphne
running. Create a file daphne_asgi.conf
in /etc/supervior/conf.d/
daphne_asgi.conf
[program:asgi_daphne]
directory=/path/to/your/project
command=/executable/path/to/daphne --bind 0.0.0.0 --port 8010 project.asgi:application
# 0.0.0.0 ip of your website
# I choose the port 8010 for daphne
stdout_logfile=/path/to/log/daphne.log
autostart=true
autorestart=true
redirect_stderr=true
run the following to update launch the daemon
sudo supervisorctl reread
sudo supervisorctl update
Here is the configuration of nginx
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream websocket {
server 0.0.0.0:8010;
}
host and port used in daphne ... --bind 0.0.0.0 --port 8010
#redirection to a https
server {
listen 80;
server_name 0.0.0.0 example.com www.example.com;
client_max_body_size 10M;
return 301 https://www.example.com$request_uri;
}
server {
listen 443 ssl default_server;
server_name www.example.com;
client_max_body_size 10M;
# ssl configuration
...
# normal http request, I use .sock
location / {
include proxy_params;
proxy_pass http://unix:/path/to/project.sock;
}
# ws request /ws/
location /ws/ {
proxy_pass http://websocket;
# this magic is needed for WebSocket
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Note that I added /ws/
in my ws urls
application = ProtocolTypeRouter({
'websocket':AllowedHostsOriginValidator(
AuthMiddlewareStack(
URLRouter(
[
url(r'^ws/$', HelloConsumer),
]
)
)
)
})
Solution 2
Most important, Use redis 5.0.9. Otherwise again error will be there.
Get it from github.com/tporadowski/redis/releases
Comments
-
Eu Chi almost 2 years
Hello Awesome People!
I created a chat room with
django-channels
. Every time I try to connect to my chat room via web socket in production, it fails. Locally it works correctly.I host on digitalocean
pip freeze:
channels==2.1.2 channels-redis==2.3.0 daphne==2.2.1 '''
I have installed the
redis-server
withsudo apt-get install redis-server
Here's my settings.
INSTALLED_APPS = [ # ''' 'channels', # ''' ] CHANNEL_LAYERS = { 'default': { 'BACKEND': 'channels_redis.core.RedisChannelLayer', 'CONFIG': { "hosts": [os.environ.get('REDIS_URL', 'redis://localhost:6379')], }, }, } ASGI_APPLICATION = "project_name.routing.application"
Here's my
asgi.py
alongsidewsgi.py
import os import django from channels.routing import get_default_application from django.core.wsgi import get_wsgi_application os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project_name.settings") django.setup() application = get_default_application()
And here's my
project_folder.rounting.py
application = ProtocolTypeRouter({ 'websocket':AllowedHostsOriginValidator( AuthMiddlewareStack( URLRouter([ # my urls ]) ) ) })
I keep getting this in firefox and something similar in other browsers:
Firefox can’t establish a connection to the server at wss://www.domain_name.com/url-to/1/XBvZjr2pqdf6fhy/
However it works locally.
UPDATE
Here is my js
var loc = window.location; var wsStart = loc.protocol == "https:" ? "wss://" : "ws://" var endpoint = wsStart + loc.host + loc.pathname var socket = new ReconnectingWebSocket(endpoint); socket.onmessage = function(e){ // code }