Hi All, I am currently facing trouble deploying Django Channels using Daphne and NGINX. I have test my code while debugging, and it is working. But when I connect it through NGINX then my connection failed. Here is how I am doing it.
asgi.py
import os
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator
from django.core.asgi import get_asgi_application
from django.urls import path
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'gml_admin.settings')
django_asgi_application = get_asgi_application()
from .routing import websocket_urlpatterns
# Django Channels WebSocket application
application = ProtocolTypeRouter(
{
"http": django_asgi_application,
"websocket": AuthMiddlewareStack(
URLRouter(websocket_urlpatterns)
),
}
)
routing.py
from django.urls import path
from admin_app.consumers import ChatConsumer, PaymentConsumer, TestConsumer
from store.consumers import TransactionConsumer
websocket_urlpatterns = [
path('ws/payment/', PaymentConsumer.as_asgi()),
path('ws/store/transaction/<str:username>/', TransactionConsumer.as_asgi()),
path('ws/test/', TestConsumer.as_asgi()),
]
admin_app/consumers.py
from channels.consumer import AsyncConsumer
from channels.generic.websocket import WebsocketConsumer
import asyncio
class TestConsumer(AsyncConsumer):
async def websocket_connect(self, event):
self.connected = True
await self.send({
"type": "websocket.accept"
})
idx=1
while self.connected:
await asyncio.sleep(2)
await self.send({
'type': 'websocket.send',
'text': f'current index: {idx}',
})
idx += 1
async def websocket_receive(self, event):
print("receive", event)
async def websocket_disconnect(self, event):
print("disconnected", event)
self.connected = False
To test the code I run following command:
daphne -p 8001 -b 0.0.0.0 gml_admin.asgi:application
and create local html file to connect to my server using websocket with following code:
test_ws.html
<html>
<head>
<script>
let webSocket = new WebSocket('ws://47.237.x.x:8001/ws/test/');
let el;
webSocket.onmessage = (event) => {
console.log(event.data);
el = document.getElementById('time');
el.innerHTML = 'Current time on server is: ' + event.data;
};
</script>s
</head>
<body>
<p id="time"></p>
</body>
</html>
and it is working, but then I want to deploy it and follows the official documentation using Supervisor Deploying — Channels 4.0.0 documentation. Here are my Supervisor and Nginx configuration:
/etc/supervisor/conf.d/gml_admin_asgi.conf
[fcgi-program:asgi]
# TCP socket used by Nginx backend upstream
socket=tcp://localhost:8001
# Directory where your site's project files are located
directory=/home/ecs-user/gml_admin/
# Each process needs to have a separate socket file, so we use process_num
# Make sure to update "mysite.asgi" to match your project name
command=/home/ecs-user/web_env/bin/daphne -u run/daphne/daphne%(process_num)d.sock --fd 0 --access-log - --proxy-headers gml_admin.asgi:application -v 3
# Number of processes to startup, roughly the number of CPUs you have
numprocs=1
# Give each process a unique name so they can be told apart
process_name=asgi%(process_num)d
# Automatically start and recover processes
autostart=true
autorestart=true
# Choose where you want your log to go
stdout_logfile=/home/ecs-user/gml_admin/logs/asgi.log
redirect_stderr=true
/etc/nginx/sites-available/gml_admin
upstream gml_admin {
server unix:/home/ecs-user/gml_admin/run/gunicorn.sock;
}
upstream daphne {
#server unix:/tmp/daphne.sock;
#server unix:/home/ecs-user/gml_admin.sock;
server localhost:8001;
}
server {
listen 8000;
# add here the ip address of your server
# or a domain pointing to that ip (like example.com or www.example.com)
server_name www.admin.gracexx.com admin.gracexx.com;
keepalive_timeout 5;
client_max_body_size 4G;
access_log /home/ecs-user/gml_admin/logs/nginx-access.log;
error_log /home/ecs-user/gml_admin/logs/nginx-error.log;
location /staticfiles/ {
root /var/www/gml_admin/;
}
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://unix:/home/ecs-user/gml_admin/run/gunicorn.sock;
proxy_send_timeout 300;
proxy_read_timeout 300;
}
location /ws/ {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_redirect off;
proxy_pass http://127.0.0.1:8001/ws/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/admin.gracexx.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/admin.gracexx.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
But then when I change my websocket connection to ws://admin.gracexx.com:8001 it failed to connect.
test_ws.html
<html>
<head>
<script>
let webSocket = new WebSocket('ws://admin.gracexx.com:8001/ws/test/');
let el;
webSocket.onmessage = (event) => {
console.log(event.data);
el = document.getElementById('time');
el.innerHTML = 'Current time on server is: ' + event.data;
};
</script>s
</head>
<body>
<p id="time"></p>
</body>
</html>
I have already try changing ws with wss but it still failed to connect.