Search code examples
djangonginxwebsocketgunicornuvicorn

Uvicorn + Django + NGinx - Error 404 while handling websockets


I am setting up a server with Nginx and Uvicorn to run a Django app with websockets.

Everything goes well with normal http request and I can get my webpage but my websockets handshakes always end up with a 404 error.

Everything goes well running with runserver.

here is my asgi.py file

import os
import django
django.setup()

from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
import MYAPP.routing
import Stressing.routing

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

application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    "websocket": AuthMiddlewareStack( URLRouter( Stressing.routing.websocket_urlpatterns ) ),
    # Just HTTP for now. (We can add other protocols later.)
})

my settings.py

ASGI_APPLICATION = 'MYAPP.asgi.application'

redis_host = os.environ.get('REDIS_HOST', '127.0.0.1')

CHANNEL_LAYERS = {
    'default': {
        'CONFIG': {
            'hosts': [(redis_host, 6379)],
        },
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
    },
}

my nginx config file

server {
    listen 80;
    server_name MYAPP.box 10.42.0.1;
    
    
    location = /favicon.ico { access_log off; log_not_found off; }
    location ~ ^/static {
        autoindex on;
        root /home/MYAPP;
    }

    location ~ ^/ {
        include proxy_params;
        proxy_pass http://unix:/home/MYAPP/MYAPP.sock;
    }
    location @proxy_to_app {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_buffering off;
        
        proxy_pass http://unix:/home/MYAPP/MYAPP.sock;
    }
    location ~ ^/ws/ {
        proxy_pass http://unix:/home/MYAPP/MYAPP.sock;
        proxy_http_version 1.1;
        proxy_redirect off;
        proxy_buffering off;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
    }
}

The request seems to reach to socket as I can see in the gunicorn log

not found /ws/0

Does anyone has an idea of the origin of the problem?


Solution

  • I have removed the regex expression from my Nginx file and it is working now

    location ~ ^/ {
    ...
    location ~ ^/ws/
    

    became

    location / {
    ...
    location /ws/
    

    so it is solved. But if someone can explain me the background of it? I thought that Nginx always prioritizes the most specific path. Is it only working without regex? (I guess there is no ways to determine which regex is more specific?!)