secure WebSocket with django

Hi,

I am new to Django and am trying to set up secure WebSocket communication between a Django-based backend and a React-based frontend. To address my issue, I reviewed the following thread, which was closed some time ago:
Secure websocket (with http)

Previously, I was working with HTTP, and my app was functioning perfectly. However, as soon as I switched to HTTPS, the WebSocket functionality stopped working as expected. I am using “sslserver” with a self-signed certificate. Below are my WebSocket URL patterns:

from django.urls import re_path
from .import consumers 

websocket_urlpatterns = [
    re_path(r'ws/flag/$', consumers.FlagConsumer.as_asgi()),  # WebSocket route
    re_path(r'ws/ar/$', consumers.ARConsumer.as_asgi()),
    re_path(r'ws/flag-spin/$', consumers.SpinFlagConsumer.as_asgi()),
]

installed apps:

INSTALLED_APPS = [
    'packaging.apps.PackagingConfig',
    'cargo_storageOpt.apps.CargoStorageoptConfig',
    'rest_framework',
    'corsheaders',
    'channels',
    'daphne',
    'sslserver',
    "django_extensions",
    'core.apps.CoreConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

When the application starts, the WebSocket communication is not established, and the terminal shows “Not Found” for all WebSocket URL patterns. Please see the attached picture for reference.

frontend:

const flagSocket = initWebSocket(`wss://${document.location.hostname}:8000/ws/flag/` , setFlag);```
``` useEffect(() => {
   const initWebSocket = (url, updateState) => {
     let socket = new WebSocket(url);

     const reconnect = () => {
       console.log(`${document.location.hostname}${window.location.protocol}xxxxxxxxxxxxxReconnecting to WebSocket at ${url}...`);
       setTimeout(() => {
         initWebSocket(url, updateState);  // Reinitialize the socket after a delay
       }, 3000);  // Retry after 3 seconds
     };

     socket.onopen = () => {
       console.log("WebSocket connection opened:", url);
     };

     socket.onmessage = (event) => {
       const data = JSON.parse(event.data);
       console.log("Data received:", data);
       if (data.is_computing !== undefined) {
         updateState(data.is_computing);
         setButtonClicked(false);
       }
     };

     socket.onerror = (error) => {
       console.error("WebSocket error:", error);
       socket.close();  // Close socket on error to trigger reconnect
     };

     socket.onclose = (event) => {
       
       // console.log("WebSocket closed:", event);
       if (!event.wasClean) {
         reconnect();  // Only reconnect if the close was unexpected
       }
     };

     return socket;
   };

Welcome @mahboobelahi !

The easiest way to handle SSL-based connections with Django is to run it behind nginx. Allow nginx to handle all the SSL “stuff”, proxying both the regular requests and the websocket connections using unencrypted protocols.

Thanks KenWhitesell. I will check ngix.

Hi,
I was traveling yesterday, so I couldn’t explain the full situation clearly.

My teammates and I are developing an app that provides cargo loading layouts for users. In our app, we use WebSockets for three main purposes because the optimizer takes more than 30 minutes to process all individuals in 100 generations of a genetic algorithm:

  1. When the optimizer starts computing, a spinner appears to indicate that the optimizer is busy.
  2. Once the optimizer finishes computing, a flag value updates, allowing the user to view the results.
  3. We use Three.js for 3D visualization of item placements in the container. This 3D visualization is accessed by clicking a button. When the user presses the button, a new tab opens (e.g., http://localhost), and a cookie-based request is sent to the backend to retrieve all layouts for display.

The WebSocket communication works perfectly with HTTP.

However, the issue arises when we start using the Meta Quest 3 VR headset to enhance the user experience. This headset requires HTTPS, and I’ve been struggling to get the WebSocket communication working in this setup. Despite my best efforts, I’ve been unable to resolve the issue.

I’m new to development and learning step by step. @KenWhitesell, you mentioned using Nginx. I’ve been exploring it but haven’t had any success yet. Is there any alternative way to achieve this functionality?

my nginx.config looks like:

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;



    # HTTPS Server Block
    server {
        listen 443 ssl;
        server_name localhost;

        # SSL Certificates
        ssl_certificate cert.pem;
        ssl_certificate_key key.pem;

        # Proxy headers
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host $http_host;

        # React frontend (served on port 3000)


        # Django backend (served on port 8000)
        location / {
            proxy_pass http://127.0.0.1:8000;  # Forward to Django backend API
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }

        # WebSocket route for Django
        location /ws/ {
            proxy_pass http://127.0.0.1:8000;  # Forward WebSocket requests to Django ASGI
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }
    }
}

now i can’t event access the test page for django backend, i tried with HTTP and https:
http://127.0.0.1:8000/
https://127.0.0.1:8000/

Is the headset itself trying to connect to the server? Or is it linked to the browser? (I’m not sure I’m understanding how it fits into this picture.)

Are you seeing the connection requests coming in to nginx?

Please post the nginx logs for these attempts.

1 Like

Couple of side notes.

First, when you’re running this behind nginx, your browser should connect to nginx at port 443 (https / wss), you do not directly connect to the application.

Second, when you’re proxying a path, you need to include that path in the target.

should be:

    location /ws/ {
        proxy_pass http://127.0.0.1:8000/ws/; 

No, the headset is not trying to connect to the server. The headset, backend, and frontend and vr apps ar on the same network.
dejango: https://localhost:8000
frontend: http://localhost:3000
VR app: https://<laptop’s local ip>:8100

I am attaching a uml diagram to highlight different apps and there interconnection:

my task is to send layout data to VR app with sockets over https .

i will update my nginx config file and post logs