[Solved] Local development setup for secured Websocket with wss

This morning, my app was working. I changed a few templates, added styles, and the sockets stopped connecting to the consumer. I have no clue.

I’m using Channels 4.0.0.

This is in frontend JS

const convSocket = new WebSocket(
    'wss://'
    + window.location.host
    + '/ws/conversation/'
    + conversation_id
    + '/'
);

document.querySelector('#message-submit').onclick = function(e) {
    const messageInputDom = document.querySelector('#message-input');
    const message = messageInputDom.value;

    convSocket.send(JSON.stringify({
        'message': message,
        'sender_id': current_user_id
    }));
};

And in my consumer :

 def connect(self):
       print("@@@@@@@@ connected to consumer @@@@@@@@@")
       ...

This is never printed. When I try to send a message from the #message-input form, I get this error :

Uncaught DOMException: An attempt was made to use an object that is not, or is no longer, usable

Basically the socket is never connected, this error happens when I try to use it.

I also get this one, more clear :

Firefox can’t establish a connection to the server at wss://127.0.0.1:8000/ws/conversation/5/.

Locally I’m using Daphne (I added it in my INSTALLED_APPS), and I launch redis with docker run --rm -p 6379:6379 redis:7. My settings for Channels looks like this :

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": ['redis://localhost:6379'],
        },
    },
}

I deployed the app with a PAAS sytem (Scalingo, Heroku-like) with gunicorn and uvicorn.
. And there I get a very unstable socket connection. It’s barely working, but sometime a message pass through.

And all of this was working this morning. Today I added a script and django-extensions, and I changed templates and added CSS and two SVG pictos. None of this seems related to Channels and Websockets. So I’m looking elsewhere, I think maybe there is a problem with my Redis setup. Also I didn’t do much settings to use wss maybe I missed something there.

What do you think ?

asgy.py file :

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

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

django_asgi_app = get_asgi_application()

import messenger.routing
from messenger.routing import websocket_urlpatterns

application = ProtocolTypeRouter(
    {
        "http": django_asgi_app,
        "websocket": AllowedHostsOriginValidator(
            AuthMiddlewareStack(URLRouter(websocket_urlpatterns))
        ),
    }
)

What command are you using to run Daphne?

(Redis as the channel layer doesn’t really have anything to do with the websocket connection itself, it’s not part of the problem here.)

You show the JavaScript as connecting to wss://..., which means you’d need to run Daphne with SSL certificates that will work with localhost or 127.0.0.1 - or, accepting the security warning for using the wrong cert or a self-signed cert, or, if you’re using certs for a domain you own, you’ll have to change your hosts file to have that domain name resolve to your local system.

To do a quick check, I reverted my local JavaScript to connecting ws:// instead of wss://, and the system got back to working flawlessly. So that was the problem, thank you for pointing me in the right direction.

Now, I just use python manage.py runserver to launch daphne, like the default mode. I don’t know how I can fake a SSL certificate locally, I will need to look into that. The first thing in my mind is that I don’t need wss when I do development locally… I could look into a way of turning it of.

And for the production problem, I will contact the support of the platform and work it with them.

I found a solution for my local setup. I added this line to my JavaScript :

const ws_scheme = window.location.protocol == 'https:' ? 'wss' : 'ws';

and I created the socket like so :

const convSocket = new WebSocket(
    ws_scheme
    + '://'
    + window.location.host
    + '/ws/conversation/'
    + conversation_id
    + '/'
);

This way, when deployed in production the socket is secured with wss, but in my local setup it’s using the default ws scheme, and I can continue to use Daphne and runserver like I did before. Problem solved with minimum effort, thank you for the help.

PS : I’m editing the topic title to reflect the problem that was solved.