I have setup django websocket on aws with daphne and I am using nginx to serve it, the setup works well, it gets connected when I test it with postman or even on vuejs. But the issue I am having now is that it disconnects when I send a message. I have tried all I could to make it work to no avail.
nginx error:
1159#1159: *1 recv() failed (104: Connection reset by peer) while proxying upgraded connection, client: 102.xx.xx.xx, server: 98.xx.xx.xx, request: "GET /ws/chat/chikjib_chikejibunoh523/?token=eyJhbxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxXQiOjE3MjY1MTYxMzMsImp0aSI6ImMzYjcxNzM4YjQ4NjRjNTU5NDFhYzAzYzMzYmUwNzdmIiwidXNlcl9pZCI6NH0.8OknTXb8IfP9oPOOV_ppGWU9exCLdBIqSXx6T1JHoV8 HTTP/1.1", upstream: "http://127.0.0.1:8001/ws/chat/chikjib_chikejibunoh523/?token=eyJhbxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxmMzYjcxNzM4YjQ4NjRjNTU5NDFhYzAzYzMzYmUwNzdmIiwidXNlcl9pZCI6NH0.8OknTXb8IfP9oPOOV_ppGWU9exCLdBIqSXx6T1JHoV8", host: "98.xx.xx.xxx"
nginx conf
server {
server_name 98.xx.xx.xxx;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
autoindex on;
alias /var/www/staticfiles/;
}
location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
location /ws/ {
proxy_pass http://127.0.0.1:8001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_redirect off;
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;
}
}
gunicorn.service
[Unit]
Description=WebSocket Daphne Service
After=network.target
[Service]
Type=simple
User=xxxxxx
WorkingDirectory=/home/xxx/src
ExecStart=/home/succour_root/succour_venv/bin/python /home/xxx/succour_venv/bin/daphne -b 127.0.0.1 -p 8001 succourBackend.asgi:application
Restart=on-failure
[Install]
WantedBy=multi-user.target
asgi.py
"""
ASGI config for succourBackend project.
It exposes the ASGI callable as a module-level variable named ``application``.
"""
import os
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "succourBackend.settings")
django.setup()
# from django.core.asgi import get_asgi_application
from channels.auth import AuthMiddlewareStack
from channels.security.websocket import AllowedHostsOriginValidator
from channels.routing import ProtocolTypeRouter, URLRouter
from succourBackend.routing import websocket_urlpatterns
from succourBackend.middleware import JWTAuthMiddleware
application = ProtocolTypeRouter(
{
"websocket":
AllowedHostsOriginValidator(
AuthMiddlewareStack(
JWTAuthMiddleware(
URLRouter(websocket_urlpatterns)
)
)
)
,
}
)
routing.py
from django.urls import re_path
from api import consumers
import logging
logger = logging.getLogger(__name__)
logger.info("Got to the route")
websocket_urlpatterns = [
re_path(r'ws/chat/(?P<room_name>[^/]+)/$', consumers.ChatConsumer.as_asgi()),
]
consumers.py
from channels.generic.websocket import AsyncWebsocketConsumer, WebsocketConsumer
import json
from channels.db import database_sync_to_async
from urllib.parse import urljoin
from api.models import ChatMessage
from api.serializers import UserProfileSerializer
from django.contrib.auth import get_user_model
User = get_user_model()
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.user = self.scope.get("user")
if not self.user.is_authenticated:
await self.close()
print("User not authenticated")
return
self.room_name = self.scope["url_route"]["kwargs"]["room_name"]
self.room_group_name = f"private_chat_{self.room_name}"
# Add user to the room group
await self.channel_layer.group_add(self.room_group_name, self.channel_name)
# Retrieve and send unread messages for this user
unread_messages = await self.get_unread_messages(self.room_group_name)
# Determine the host to build absolute URLs
protocol = "https" if self.scope.get("scheme") == "https" else "http"
host = f"{protocol}://{self.scope['server'][0]}:{self.scope['server'][1]}"
for message in unread_messages:
profile_picture_url = None
if message["profile_picture"]:
profile_picture_url = urljoin(host, message["profile_picture"].url)
await self.channel_layer.group_send(
self.room_group_name,
{
"type": "private_chat_message",
"message": message["message"],
"username": message["sender_username"],
"timestamp": message["timestamp"].isoformat(),
"sender": {
"full_name": message["full_name"],
"type": message["type"],
"profile_picture": profile_picture_url,
},
},
)
await self.accept()
print("User connected to the room:", self.room_name)
async def disconnect(self, close_code):
# Remove user from the room group
await self.channel_layer.group_discard(self.room_group_name, self.channel_name)
print("User disconnected from the room:", self.room_name)
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json.get("message")
recipient_username = text_data_json.get("recipient")
if recipient_username:
recipient_user = await self.get_user_by_username(recipient_username)
if recipient_user:
# Check if the user is part of this chat
# if not self.is_user_in_chat(recipient_user):
# print("User not authorized to join this chat")
# return
await self.save_private_message(
self.user.id, recipient_user.id, message, self.room_group_name
)
await self.channel_layer.group_send(
self.room_group_name,
{
"type": "private_chat_message",
"message": message,
"username": self.user.username,
},
)
async def private_chat_message(self, event):
message = event["message"]
username = event["username"]
timestamp = event["timestamp"]
await self.send(
text_data=json.dumps(
{
"message": message,
"username": username,
"timestamp": timestamp,
"sender": event["sender"],
"type": "private_chat",
}
)
)
@database_sync_to_async
def save_private_message(self, sender_id, recipient_id, message, group_name):
sender = User.objects.get(id=sender_id)
recipient = User.objects.get(id=recipient_id)
return ChatMessage.objects.create(
sender=sender, recipient=recipient, message=message, group_name=group_name
)
@database_sync_to_async
def get_user_by_username(self, username):
try:
return User.objects.get(username=username)
except User.DoesNotExist:
return None
@database_sync_to_async
def get_unread_messages(self, group_name):
# Get all messages for the specified group
messages = ChatMessage.objects.filter(group_name=group_name)
# print(UserProfileSerializer(messages[0].sender).data)
return [
{
"message": message.message,
"sender_username": message.sender.username,
"timestamp": message.timestamp,
"full_name": message.sender.get_full_name(),
"type": message.sender.type,
"profile_picture": message.sender.profile_picture,
}
for message in messages
]
def is_user_in_chat(self, recipient_user):
# Check if the user and recipient are part of this chat room
users_in_chat = self.room_name.split("__")
return (
self.user.username in users_in_chat
and recipient_user.username in users_in_chat
)
async def chat_message(self, event):
message = event["message"]
username = event["username"]
await self.send(
text_data=json.dumps(
{
"message": message,
"username": username,
}
)
)
self.send(
text_data=json.dumps(
{
"message": "message",
}
)
)
Please what could be the cause. I need help.