Django websocket connection on Render not established

I have a django websocket project I have deployed to render. It isn’t able to establish connection in production but it works perfectly fine testing locally.

Here is the error log;
Not Found: /ws/course-group-chat/5/
127.0.0.1 - - [29/Jan/2024:18:12:03 +0000] “GET /ws/course-group-chat/5/?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzEwMDA0MTQ1LCJpYXQiOjE3MDY1NDgxNDUsImp0aSI6IjQ1NGE5ZWVhZjk5YTRhZmZiZTM4ODYxYWNlZjNkYzk2IiwidXNlcl9pZCI6MSwiZW1haWwiOiJmZWxpeGFjaGlhaEBnbWFpbC5jb20iLCJ1c2VybmFtZSI6IkppbSBCZXJrIn0.vU72Z9oYq04S2nVE8c149OaLpC-7OqADrP2V1nHEKDo HTTP/1.1” 404 2789 “-” “Go-http-client/1.1”

This is my ‘Procfile’;
web: gunicorn Skuluu.wsgi:application -w 4
websocket: daphne Skuluu.asgi:application -p $PORT -b 0.0.0.0

asgi.py
import os
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
from channels.security.websocket import AllowedHostsOriginValidator
from chat.middlewares import JWTAuthMiddlewareStack

import chat.routing

os.environ.setdefault(‘DJANGO_SETTINGS_MODULE’, ‘Skuluu.settings’)

application = ProtocolTypeRouter(
{
# Django’s ASGI application to handle traditional HTTP requests
‘http’: get_asgi_application(),

    # WebSocket chat handler
    'websocket': AllowedHostsOriginValidator(
        JWTAuthMiddlewareStack(
            URLRouter(
                chat.routing.websocket_urlpatterns
            )
        )   
    )
}

)

routing.py
from django.urls import re_path
from . import consumers

websocket_urlpatterns = [
re_path(r’ws/course-group-chat/(?P<course_group_id>\d+)/$', consumers.CourseGroupConsumer.as_asgi()),
]

consumers.py
import json
from channels.generic.websocket import AsyncWebsocketConsumer
from channels.db import database_sync_to_async
from .models import CourseGroup, CourseGroupMessage

class CourseGroupConsumer(AsyncWebsocketConsumer):

async def connect(self):
    # Authenticate the user
    if self.scope["user"].is_anonymous:
        await self.close()
        return

    # Extract course_group_id from the URL route
    course_group_id = self.scope['url_route']['kwargs']['course_group_id']

    # Check if the user is a member of the specified course group
    if not self.is_user_in_course_group(self.scope["user"], course_group_id):
        await self.close()
        return

    # Create a unique room name for the course group
    self.room_group_name = f"course_group_{course_group_id}"

    # Add the user to the WebSocket group
    await self.channel_layer.group_add(
        self.room_group_name,
        self.channel_name
    )

    # Accept the WebSocket connection
    await self.accept()

    # Send a connection established message to the user
    await self.send(text_data=json.dumps({
        'type': 'connection_established',
        'message': 'You are now connected!'
    }))

async def disconnect(self, code):
    # Remove the user from the WebSocket group upon disconnection
    if hasattr(self, 'room_group_name') and self.room_group_name:
        # Remove the user from the WebSocket group upon disconnection
        await self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name
        )

Start command in my render settings is gunicorn Skuluu.wsgi:application

I’m guessing that could be the reason why the websocket connection is not being found.

I think you need to take gunicorn out and just use daphne. Channels won’t work in a wsgi environment.

Follow through the docs here Tutorial Part 1: Basic Setup — Channels 4.0.0 documentation and it’ll take you through serving HTTP and ws via daphne.

Okay, I’ll try that. I literally didn’t know daphne can server both ws and HTTP.
Thanks. I’ll give you a feedback.

1 Like

Hello @KSD89, I added this daphne command, daphne Skuluu.asgi:application -b 0.0.0.0 -p $PORT as the start command on render and this error occurred during deployment.
Error

==> Build successful 🎉 ==> Deploying... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "<frozen importlib._bootstrap>", line 1204, in _gcd_import File "<frozen importlib._bootstrap>", line 1176, in _find_and_load File "<frozen importlib._bootstrap>", line 1147, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 690, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 940, in exec_module File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed File "/opt/render/project/src/Skuluu/asgi.py", line 15, in <module> from chat.middlewares import JWTAuthMiddlewareStack File "/opt/render/project/src/chat/middlewares.py", line 2, in <module> from rest_framework_simplejwt.authentication import JWTAuthentication File "/opt/render/project/src/.venv/lib/python3.11/site-packages/rest_framework_simplejwt/authentication.py", line 4, in <module> from django.contrib.auth.models import AbstractBaseUser File "/opt/render/project/src/.venv/lib/python3.11/site-packages/django/contrib/auth/models.py", line 3, in <module> from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager File "/opt/render/project/src/.venv/lib/python3.11/site-packages/django/contrib/auth/base_user.py", line 57, in <module> class AbstractBaseUser(models.Model): File "/opt/render/project/src/.venv/lib/python3.11/site-packages/django/db/models/base.py", line 129, in __new__ app_config = apps.get_containing_app_config(module) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/render/project/src/.venv/lib/python3.11/site-packages/django/apps/registry.py", line 260, in get_containing_app_config self.check_apps_ready() File "/opt/render/project/src/.venv/lib/python3.11/site-packages/django/apps/registry.py", line 138, in check_apps_ready raise AppRegistryNotReady("Apps aren't loaded yet.") django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet. ==> Common ways to troubleshoot your deploy: https://docs.render.com/troubleshooting-deploys ==> Using Node version 20.10.0 (default) ==> Docs on specifying a Node version: https://render.com/docs/node-version ==> Running 'daphne Skuluu.asgi:application -b 0.0.0.0 -p $PORT' Traceback (most recent call last): File "/opt/render/project/src/.venv/bin/daphne", line 8, in <module> sys.exit(CommandLineInterface.entrypoint()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/render/project/src/.venv/lib/python3.11/site-packages/daphne/cli.py", line 171, in entrypoint cls().run(sys.argv[1:]) File "/opt/render/project/src/.venv/lib/python3.11/site-packages/daphne/cli.py", line 233, in run application = import_by_path(args.application) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/render/project/src/.venv/lib/python3.11/site-packages/daphne/utils.py", line 12, in import_by_path target = importlib.import_module(module_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/importlib/__init__.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "<frozen importlib._bootstrap>", line 1204, in _gcd_import File "<frozen importlib._bootstrap>", line 1176, in _find_and_load File "<frozen importlib._bootstrap>", line 1147, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 690, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 940, in exec_module File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed File "/opt/render/project/src/Skuluu/asgi.py", line 15, in <module> from chat.middlewares import JWTAuthMiddlewareStack File "/opt/render/project/src/chat/middlewares.py", line 2, in <module> from rest_framework_simplejwt.authentication import JWTAuthentication File "/opt/render/project/src/.venv/lib/python3.11/site-packages/rest_framework_simplejwt/authentication.py", line 4, in <module> from django.contrib.auth.models import AbstractBaseUser File "/opt/render/project/src/.venv/lib/python3.11/site-packages/django/contrib/auth/models.py", line 3, in <module> from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager File "/opt/render/project/src/.venv/lib/python3.11/site-packages/django/contrib/auth/base_user.py", line 57, in <module> class AbstractBaseUser(models.Model): File "/opt/render/project/src/.venv/lib/python3.11/site-packages/django/db/models/base.py", line 129, in __new__ app_config = apps.get_containing_app_config(module) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/render/project/src/.venv/lib/python3.11/site-packages/django/apps/registry.py", line 260, in get_containing_app_config self.check_apps_ready() File "/opt/render/project/src/.venv/lib/python3.11/site-packages/django/apps/registry.py", line 138, in check_apps_ready raise AppRegistryNotReady("Apps aren't loaded yet.") django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet. ==> Using Node version 20.10.0 (default) ==> Docs on specifying a Node version: https://render.com/docs/node-version ==> Running 'daphne Skuluu.asgi:application -b 0.0.0.0 -p $PORT' Traceback (most recent call last): File "/opt/render/project/src/.venv/bin/daphne", line 8, in <module> sys.exit(CommandLineInterface.entrypoint()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/render/project/src/.venv/lib/python3.11/site-packages/daphne/cli.py", line 171, in entrypoint cls().run(sys.argv[1:]) File "/opt/render/project/src/.venv/lib/python3.11/site-packages/daphne/cli.py", line 233, in run application = import_by_path(args.application) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/render/project/src/.venv/lib/python3.11/site-packages/daphne/utils.py", line 12, in import_by_path target = importlib.import_module(module_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/importlib/__init__.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "<frozen importlib._bootstrap>", line 1204, in _gcd_import File "<frozen importlib._bootstrap>", line 1176, in _find_and_load File "<frozen importlib._bootstrap>", line 1147, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 690, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 940, in exec_module File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed File "/opt/render/project/src/Skuluu/asgi.py", line 15, in <module> from chat.middlewares import JWTAuthMiddlewareStack File "/opt/render/project/src/chat/middlewares.py", line 2, in <module> from rest_framework_simplejwt.authentication import JWTAuthentication File "/opt/render/project/src/.venv/lib/python3.11/site-packages/rest_framework_simplejwt/authentication.py", line 4, in <module> from django.contrib.auth.models import AbstractBaseUser File "/opt/render/project/src/.venv/lib/python3.11/site-packages/django/contrib/auth/models.py", line 3, in <module> from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager File "/opt/render/project/src/.venv/lib/python3.11/site-packages/django/contrib/auth/base_user.py", line 57, in <module> class AbstractBaseUser(models.Model): File "/opt/render/project/src/.venv/lib/python3.11/site-packages/django/db/models/base.py", line 129, in __new__ app_config = apps.get_containing_app_config(module) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/render/project/src/.venv/lib/python3.11/site-packages/django/apps/registry.py", line 260, in get_containing_app_config self.check_apps_ready() File "/opt/render/project/src/.venv/lib/python3.11/site-packages/django/apps/registry.py", line 138, in check_apps_ready raise AppRegistryNotReady("Apps aren't loaded yet.") django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.

Can you paste your asgi.py file?

Sure.

Updates on the error, I figured it out.
I had to bring in these codes in this arrangement.
`import os

Set the Django settings module

os.environ.setdefault(‘DJANGO_SETTINGS_MODULE’, ‘Skuluu.settings’)

import django

Call django.setup() to populate Django’s application registry

django.setup()`

But now I’m getting a different error related to authentication. Since I’m using daphne for both HTTP and Websocket requests.

I get an error logging in via the http protocol.
Here’s the error;

Your service is live 🎉 2024-01-30 13:21:50,646 ERROR Internal Server Error: / Traceback (most recent call last): File "/opt/render/project/src/.venv/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner response = get_response(request) ^^^^^^^^^^^^^^^^^^^^^ TypeError: JWTAuthMiddleware.__call__() missing 2 required positional arguments: 'receive' and 'send' 2024-01-30 13:27:01,724 ERROR Internal Server Error: /api/user-auth/login/ Traceback (most recent call last): File "/opt/render/project/src/.venv/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner response = get_response(request) ^^^^^^^^^^^^^^^^^^^^^ TypeError: JWTAuthMiddleware.__call__() missing 2 required positional arguments: 'receive' and 'send'

Here’s my middlewares and asgi code respectively,

middlewares.py

`from channels.auth import AuthMiddlewareStack
from django.contrib.auth.models import AnonymousUser
from django.db import close_old_connections
from jwt import decode as jwt_decode
from django.conf import settings
from user_auth.models import User
from channels.db import database_sync_to_async

class JWTAuthMiddleware:
def init(self, inner):
self.inner = inner

async def __call__(self, scope, receive, send):
    close_old_connections()
    query_string = scope.get('query_string', b'').decode()
    headers = dict(scope['headers'])

    # Extract JWT token from query parameters or headers
    if 'token' in query_string:
        token = query_string.split('=')[1]
    elif b'authorization' in headers:
        token = headers[b'authorization'].decode().split()[1]
    else:
        token = None


    if token:
        try:
            # Decode JWT token and get user_id
            payload = jwt_decode(token, settings.SECRET_KEY, algorithms=['HS256'])

            user_id = payload['user_id']

            # Fetch user object from the database asynchronously
            user = await self.get_user_by_id(user_id)
            scope['user'] = user

        except Exception as e:
            scope['user'] = AnonymousUser()

    return await self.inner(scope, receive, send)

@staticmethod
@database_sync_to_async
def get_user_by_id(user_id):
    return User.objects.get(id=user_id)

def JWTAuthMiddlewareStack(inner):
return JWTAuthMiddleware(AuthMiddlewareStack(inner))
`

asgi.py

`
import os

Set the Django settings module

os.environ.setdefault(‘DJANGO_SETTINGS_MODULE’, ‘Skuluu.settings’)

import django

Call django.setup() to populate Django’s application registry

django.setup()

from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
from channels.security.websocket import AllowedHostsOriginValidator
from chat.middlewares import JWTAuthMiddlewareStack
import chat.routing

Get the ASGI application for Django

django_asgi_app = get_asgi_application()

Define the WebSocket application

application = ProtocolTypeRouter({
# Handle traditional HTTP requests
‘http’: django_asgi_app,

# Handle WebSocket connections with JWT authentication middleware
'websocket': AllowedHostsOriginValidator(
    JWTAuthMiddlewareStack(
        URLRouter(chat.routing.websocket_urlpatterns)
    )
),

})
`

Please where you able to fix the issue??

I’ve been trying to get this working too.