I did a chatting part in my web app with django it works perfectly in local but after I deployed it to heroku , it doesn't work: this is my consumers.py class:
from channels.generic.websocket import AsyncWebsocketConsumer
from django.contrib.auth.models import User
from django.db.models import Q
from asgiref.sync import sync_to_async
import json
from chat.models import Thread, Message
from users.serializers import UserSerializer
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
friend = None
me = self.scope['user'] # logged in user
friend_name = self.scope['url_route']['kwargs']['friend'] # get the username of that user, whoom you want to chat
friend_instance = await sync_to_async(User.objects.get, thread_sensitive=True)(username=friend_name) # get user object of friend
# create a new Thread object if thread of specific chat does not exists, otherwise return the thread
thread = None
try:
thread = await sync_to_async(Thread.objects.get, thread_sensitive=True)((Q(user1=me) & Q(user2=friend_instance)) | (Q(user1=friend_instance) & Q(user2=me)))
except:
thread = await sync_to_async(Thread.objects.create, thread_sensitive=True)(user1=me, user2=friend_instance)
self.room_name = thread.room_name # room name
await self.channel_layer.group_add(
self.room_name,
self.channel_name
)
await self.accept()
async def disconnect(self, close_code):
'''
disconnect the websocket connection.
'''
await self.channel_layer.group_discard (
self.room_name,
self.channel_name
)
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
from_user = text_data_json['user']
to_user = text_data_json['friend']
from_user_instanse = await sync_to_async(User.objects.get, thread_sensitive=True)(username=from_user['username']) # get user object of friend
to_user_instanse = await sync_to_async(User.objects.get, thread_sensitive=True)(username=to_user['username']) # get user object of friend
thread_obj = await sync_to_async(Thread.objects.get, thread_sensitive=True)((Q(user1=from_user_instanse) & Q(user2=to_user_instanse)) | (Q(user1=to_user_instanse) & Q(user2=from_user_instanse)))
message_instane = await sync_to_async(Message.objects.create, thread_sensitive=True)(messag_body=message, from_user=from_user_instanse, to_user=to_user_instanse, thread=thread_obj)
await self.channel_layer.group_send(
self.room_name,
{
'type': 'chatroom_messages',
'message': message_instane.messag_body,
'user': message_instane.from_user
}
)
async def chatroom_messages(self, event):
message = event['message']
user = event['user']
user_serialized_data = UserSerializer(user)
await self.send(text_data=json.dumps({
'message': message,
'user': user_serialized_data.data
}))
in the template this is the connection request part with js:
chatSocket.send(JSON.stringify({ //the error shows in this part that WebSocket is already in CLOSING or CLOSED state
'message': msg,
'user': me,
'friend': friendName
}));
....
/* connection request */
const chatSocket = new WebSocket(
'wss://'
+ window.location.host
+ '/ws/chat/'
+ friendName['username']
+ '/'
);
in my chat app this I have routing.py
from django.urls import re_path
from . import consumers
websocket_urlpatterns = [
re_path(r'ws/chat/(?P<friend>\w+)/$', consumers.ChatConsumer.as_asgi()),
]
in my project I have also routing.py
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
import chat.routing
application = ProtocolTypeRouter ({
'websocket': AuthMiddlewareStack(
URLRouter (
chat.routing.websocket_urlpatterns
)
)
})
and this is actually my asgi.py :
import os
import django #added
#from django.core.asgi import get_asgi_application #removed
from channels.routing import get_default_application # added
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
django.setup() #added
application = get_default_application() #added
#application = get_asgi_application() #removed
in my procfile :
release: python manage.py migrate
web: daphne myproject.asgi:application --port $PORT --bind 0.0.0.0 -v2
worker: python manage.py runworker channels --settings=myproject.settings -v2
in my settings.py
ASGI_APPLICATION = "myproject.routing.application"
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [os.environ.get('REDIS_URL', 'redis://localhost:6379')],
},
},
}
it works perfectly in local but not anymore working after deployement, am I messing something
this is heroku logs :
......
2021-12-29T18:15:42.187913+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packa
ges/aioredis/connection.py", line 111, in create_connection
2021-12-29T18:15:42.187913+00:00 app[web.1]: reader, writer = await asyncio.wait_for(open_conne
ction(
2021-12-29T18:15:42.187916+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/asyncio/ta
sks.py", line 442, in wait_for
2021-12-29T18:15:42.187916+00:00 app[web.1]: return await fut
2021-12-29T18:15:42.187916+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packa
ges/aioredis/stream.py", line 23, in open_connection
2021-12-29T18:15:42.187916+00:00 app[web.1]: transport, _ = await get_event_loop().create_conne
ction(
2021-12-29T18:15:42.187917+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/asyncio/ba
se_events.py", line 1056, in create_connection
2021-12-29T18:15:42.187917+00:00 app[web.1]: raise exceptions[0]
2021-12-29T18:15:42.187917+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/asyncio/ba
se_events.py", line 1041, in create_connection
2021-12-29T18:15:42.187917+00:00 app[web.1]: sock = await self._connect_sock(
2021-12-29T18:15:42.187917+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/asyncio/ba
se_events.py", line 955, in _connect_sock
2021-12-29T18:15:42.187918+00:00 app[web.1]: await self.sock_connect(sock, address)
2021-12-29T18:15:42.187918+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/asyncio/se
lector_events.py", line 502, in sock_connect
2021-12-29T18:15:42.187918+00:00 app[web.1]: return await fut
2021-12-29T18:15:42.187918+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/asyncio/se
lector_events.py", line 537, in _sock_connect_cb
2021-12-29T18:15:42.187919+00:00 app[web.1]: raise OSError(err, f'Connect call failed {address}
')
2021-12-29T18:15:42.187919+00:00 app[web.1]: ConnectionRefusedError: [Errno 111] Connect call f
ailed ('127.0.0.1', 6379)
2021-12-29T18:15:42.188173+00:00 app[web.1]: 2021-12-29 18:15:42,188 INFO failing WebSocket
opening handshake ('Internal server error')
2021-12-29T18:15:42.188439+00:00 app[web.1]: 2021-12-29 18:15:42,188 WARNING dropping connecti
on to peer tcp4:10.1.93.62:26296 with abort=False: Internal server error
2021-12-29T18:15:42.189132+00:00 app[web.1]: 2021-12-29 18:15:42,189 DEBUG WebSocket closed
for ['10.1.93.62', 26296]
2021-12-29T18:15:42.189195+00:00 app[web.1]: 10.1.93.62:26296 - - [29/Dec/2021:18:15:42] "WSDIS
CONNECT /ws/chat/person/" - -