nginx point websocket to http - GET /ws/chat/ HTTP/1.1" 404 Not Found - daphne - channels - websocket

Hi
I have an issue with deploying my django project containing WebSocket
my project works fine in local, and when I deploy on the Ubuntu server using this command(for testing)

uvicorn myproj.asgi:application --host 0.0.0.0 --port 8000

the project runs successfully, and when I enter my server IP in the browser, like http://188.245.*.*:8000
everything works fine and WebSocket connects, in terminal I see this log: "WebSocket /ws/chat/" [accepted] :point_left:



BUT error occurs when I try to enter my_domain and connect to WebSocket,

I wrote a configuration and tested many solutions to config nginx to use my domain name,
but when I use http://domain.com I see this log in the terminal :
"GET /ws/chat/ HTTP/1.1" 404 Not Found

It is something like that nginx redirects Websoket to HTTP :thinking:

the page console when I entered the domain:

my nginx config is /etc/nginx/sites-available/myproject :

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

server {
        error_log /var/log/nginx/app_error.log debug;
    listen 80;
    server_name my_domain.com;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        alias /home/projectdir/static_files/;
    }

    location /ws/ {
        proxy_pass http://0.0.0.0:8000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        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 X-Forwarded-Proto $scheme;
        proxy_read_timeout 86400;
        proxy_connect_timeout 86400;
        proxy_send_timeout 86400;
    }

    location / {
        proxy_pass http://0.0.0.0:8080;
        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 X-Forwarded-Proto $scheme;
    }
}

I used many different configs and nothing works, and I use some AI bots but still have problems.



some of my codes are below:
settings.py:

...
INSTALLED_APPS = [
    "daphne",
. . . other installed apps
]
 
ASGI_APPLICATION = "myproj.asgi.application"
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [("127.0.0.1", 6379)],
        },
    },
}
 . . . 


asgi file:

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

from messaging.routing import websocket_urlpatterns

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

django_asgi_app = get_asgi_application()

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


messaging.routong :

from django.urls import re_path, path

from . import consumers

websocket_urlpatterns = [
    re_path(r'^ws/chat/$', consumers.CombinedConsumer.as_asgi()),
]


and consumer is:

class CombinedConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.user = self.scope['user']

        await self.channel_layer.group_add("broadcast", self.channel_name)

        await self.accept()

 . . .other methods . . .


js code is:

var ws_scheme = window.location.protocol === "https:" ? "wss" : "was";
    
const chatSocket = new WebSocket(
        ws_scheme
        + '://'
        + window.location.host
        + '/ws/chat/'
    );

Welcome @mohammadrezaelahi !

The first thing I’d try is:

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

(That’s how I have it configured.)

Also, as a general rule, I’d change the sending address to 127.0.0.1. I’ve never tried to proxy to 0.0.0.0.

thanks for your answer,
I change it to this:

location /ws/ {
        proxy_pass http://0.0.0.0:8000/ws/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }


    location / {
        proxy_pass http://0.0.0.0:8080;
        include proxy_params;
    }

and still not working,
I see in uvicorn terminal log a HTTP request sent and not found,
I write a logger in my asgi:

class LoggingMiddleware:
    def __init__(self, inner):
        self.inner = inner

    async def __call__(self, scope, receive, send):
        logger.error(f"ASGI request: {scope['type']} {scope.get('path', 'N/A')}")
        logger.error(f"ASGI scope: {scope}")
        return await self.inner(scope, receive, send)


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

and in logs I see this:
ERROR ASGI request: http /ws/chat/
ERROR ASGI scope: {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.4'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8000), 'client': ('37.156.*.*', 0), 'scheme': 'http', 'root_path': '', 'headers': [(b'connection', b'upgrade'), (b'host', b'0.0.0.0:8000'), (b'x-forwarded-for', b'37.156.*.*), (b'x-real-ip', b'37.156.*.*), (b'x-xss-protection', b'1; mode=block'), (b'x-url-scheme', b': http'), (b'pragma', b'no-cache'), (b'cache-control', b'no-cache'), (b'user-agent', b'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36'), (b'origin', b'http://my_domain.com'), (b'sec-websocket-version', b'13'), (b'accept-encoding', b'gzip, deflate'), (b'accept-language', b'en-US,en;q=0.9,fa-IR;q=0.8,fa;q=0.7,en-GB;q=0.6'), (b'cookie', b'csrftoken=BMY1NlHvlgIUwE25IHkkB13WjU6vb6tW; sessionid=ao4gxfzm8qnhs2se5dwq4cx0mr1rehnx'), (b'sec-websocket-key', b'XLkuzC7E6jGcBTlBbPNNEw=='), (b'sec-websocket-extensions', b'permessage-deflate; client_max_window_bits')], 'state': {}, 'method': 'GET', 'path': '/ws/chat/', 'raw_path': b'/ws/chat/', 'query_string': b''}

I’d still suggest you change the address to 127.0.0.1, seeing the 0.0.0.0 there seems very odd to me. (And, that would be the preferred address for the request to be proxied to and not the host system’s address.

Also:

That’s a copy/paste error? "was" is not a valid scheme, it would need to be "ws". (If you actually have that in your code, that needs to be fixed.)

Can you post your complete asgi.py file?

Admittedly, beyond these two items, I’m at a bit of a loss. (I don’t use uvicorn and I use separate processes for Django and Channels.)