5

I'm trying to set up a WebSocket connection using Django Channels in my Django project. However, I keep encountering an error when trying to connect from the frontend JavaScript. The error message in the browser console is:

WebSocket connection to 'wss://example.com/wss/' failed

Here is my project structure:

project/
    ├── myproject/
    │   ├── __init__.py
    │   ├── settings.py
    │   ├── urls.py
    │   ├── wsgi.py
    │   ├── asgi.py
    ├── myapp/
    │   ├── __init__.py
    │   ├── views.py
    │   ├── urls.py
    │   ├── consumers.py
    │   ├── routing.py
    │   ├── templates/
    │       ├── index.html
    ├── manage.py
    ├── passenger_wsgi.py
    ├── requirements.txt

My settings.py includes:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'channels',
]

ASGI_APPLICATION = 'myproject.asgi.application'

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels.layers.InMemoryChannelLayer',
    },
}

The asgi.py file is configured as follows:

import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
import myapp.routing

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')

application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    "websocket": AuthMiddlewareStack(
        URLRouter(
            myapp.routing.websocket_urlpatterns
        )
    ),
})

My routing.py:

from django.urls import path
from . import consumers

websocket_urlpatterns = [
    path('wss/', consumers.LoadConsumer.as_asgi()),
]

The consumer class in consumers.py:

from channels.generic.websocket import AsyncWebsocketConsumer

class LoadConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        await self.accept()

    async def disconnect(self, close_code):
        pass

    async def receive(self, text_data):
        pass

And here is the JavaScript code for the WebSocket connection:

const socket = new WebSocket('wss://example.com/wss/');

socket.onopen = function(event) {
    console.log("WebSocket is open now.");
};

socket.onmessage = function(event) {
    console.log("WebSocket message received:", event);
};

socket.onclose = function(event) {
    console.log("Connection closed");
};

socket.onerror = function(error) {
    console.log("WebSocket Error:", error);
};

enter image description here

Edit

from django.urls import re_path
from . import consumers

websocket_urlpatterns = [
    re_path('ws/', consumers.LoadConsumer.as_asgi()),
]
8
  • Which ASGI server are you using in this production environment? Commented Jun 26, 2024 at 17:23
  • Daphne I guess. Commented Jun 27, 2024 at 13:26
  • Can you confirm? Commented Jun 27, 2024 at 13:40
  • I can't as I'm in a host and I don't have access to terminal like they do in VPS to run or check commands. Commented Jun 27, 2024 at 15:27
  • Should I ask my provincer? Commented Jun 27, 2024 at 15:28

2 Answers 2

2

I found it! Or at least I think I did. Starting in Django 2.0, path() was introduced as a simpler way to write URL paths in Django. Unfortunately this doesn’t provide everything Django Channels needs to provide routing. In their own words:

Note we use re_path() due to limitations in URLRouter.

I have no idea what limitations they encountered but it is plausible because even the Django team acknowledges that path() is a simpler interface while re_path() is for finer control and more versatility.

Most people actually make this mistake too so you are not alone in this. [1]

Change your code from using path() to using re_path() and you will be fine.


[1] Here [github] is one such case posited in the answer.

Sign up to request clarification or add additional context in comments.

3 Comments

Tried it, Didn't worked
Try this: re_path(r"^wss/$", •••) because that is what you have in the Javascript of the OP. If it doesn’t work then we are looking at the wrong place.
Also tried that and didn't work (yeah that ws was my mistake i should've put wss but it didn't work anyways)
1

Add 'daphne' to the top of the INSTALLED_APPS setting, not 'channels'.
Tutorial: https://channels.readthedocs.io/en/latest/tutorial/part_1.html#integrate-the-channels-library

INSTALLED_APPS = [
    'daphne',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # 'channels',
]

Also check whether you intended 'wss://example.com/wss/' (with your deployed domain) or 'wss://127.0.0.1:8000/wss/'.

5 Comments

Do you see Starting ASGI/Daphne version 3.0.2 development server at http://127.0.0.1:8000/when you runserver?
N‌o‌ ‌I‌ ‌d‌o‌n‌'‌t‌.
Actually I don't know where to see logs I only know how to see errors.
Are you running from terminal or deploying?
I'm running on cpanel.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.