djangodjango-rest-frameworkwebsocketdaphne

Unable to open Secure Websocket Requests with Daphne + Django Rest Framework


I want to enable secure websocket connection to my Django Rest Framework application. I see that all services are starting correctly, but still when I try to connect via the following URL, the connection does not get established. It just fails with no trace.

wss://127.0.0.1:8000/ws/notifications/

Where as it works fine over ws

ws://127.0.0.1:8000/ws/notifications/

docker-compose.yml

services:
  api:
    platform: linux/amd64
    build:
      context: .
      dockerfile: Dockerfile.dev
    command: 'sh -c "./manage.py migrate && python manage.py runserver 0.0.0.0:8080"'
    restart: always
    networks:
      - default
      - fake_microservices
    volumes:
      - ./:/app
      - $HOME/.aws:/root/.aws:ro
      - /var/run/docker.sock:/var/run/docker.sock
      - type: bind
        source: ./docker/cpuinfo_with_fake_speed.txt
        target: /proc/cpuinfo
    ports:
      - 8080:8080
    env_file:
      - ./.env
    depends_on:
      - db

  daphne:
    platform: linux/amd64
    build:
      context: .
      dockerfile: Dockerfile.dev
    command: 'sh -c "daphne -v 3 --access-log daphne.log -b 0.0.0.0 -p 8000  apps.asgi:application"'
    restart: always
    working_dir:  /app
    volumes:
      - ./:/app
      - /var/run/docker.sock:/var/run/docker.sock

asgi.py

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.local")

django_asgi_app = get_asgi_application()
from channels.routing import ProtocolTypeRouter, URLRouter

application = ProtocolTypeRouter(
    {
        "http": django_asgi_app,
        "websocket": URLRouter([path('ws/notifications/', NotificationConsumer.as_asgi())]),
    }
)

I can see that Daphne starts with no problems:

daphne_1   | 2023-04-06 09:05:27,576 INFO     Starting server at tcp:port=8000:interface=0.0.0.0
daphne_1   | 2023-04-06 09:05:27,578 INFO     HTTP/2 support enabled
daphne_1   | 2023-04-06 09:05:27,578 INFO     Configuring endpoint tcp:port=8000:interface=0.0.0.0
daphne_1   | 2023-04-06 09:05:27,580 INFO     HTTPFactory starting on 8000
daphne_1   | 2023-04-06 09:05:27,585 INFO     Starting factory <daphne.http_protocol.HTTPFactory object at 0x7f93ca9abc40>
daphne_1   | 2023-04-06 09:05:27,587 INFO     Listening on TCP address 0.0.0.0:8000

api_1      | Django version 3.2.14, using settings 'config.local'
api_1      | Starting ASGI/Channels version 3.0.5 development server at http://0.0.0.0:8080/
api_1      | Quit the server with CONTROL-C.

The app is configured with the port 8080.

I suspect that Daphne is not picking up the wss request at all.
Can someone please help?


Solution

  • Remember, when using Daphne Channels, you are actually setting up Daphne to redirect web traffic and run separate containers. Juxtaposed to other languages where your websocket would connect to another server, we are connecting to the same server. Thus, we are connecting to our localhost, and you can expect that it will work with ws.

    The problem, as you may be aware, is using Daphne with wss as is required for a website in production.

    Consider the following apache server configuration, if you are running locally then you should not have to rewrite any rules for /ws/ but if you are at production level you will need to redirect your http and ws connections to https and wss

    <VirtualHost _default_:443>
    ...
    RewriteEngine on
    RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC,OR]
    RewriteCond %{HTTP:CONNECTION} ^Upgrade$ [NC]
    RewriteRule .* ws://127.0.0.1:8001%{REQUEST_URI} [P,QSA,L]
    ProxyPass /wss/ wss://127.0.0.1:8001/
    ProxyPassReverse /wss/ wss://127.0.0.1:8001/
    ...