Ошибка 404 Websocket после развертывания в домене

Я установил вебсокеты (модуль чата) в свое приложение Django, оно отлично работает на моей локальной машине, но когда я развернул свое приложение на amazon ec2 instance с контейнеризацией, оно говорит 404 Not Found при тестировании через postman.

В журналах моего контейнера ASGI также говорится о том же самом:

WARNING  Not Found: /chat/1/
IP:47942 - - [XX:XX:XX] "GET /chat/1/" 404 4479

Обратите внимание, что с контейнерами Docker проблем нет - я тоже пробовал с контейнерами на своей локальной машине, и все работало.

Вот мой файл nginx:

upstream app-development-asgi {
  ip_hash;
  server app-development-asgi:8001;
}

upstream app-development-wsgi {
  ip_hash;
  server app-development-wsgi:8000;
}

server {
    listen 80;

    server_name domain_name;

    location /static/ {
        alias /app-development/staticfiles/;
    }

    location /media/ {
        alias /app-development/media/;
    }

    location /ws/ {
        proxy_pass http://app-development-asgi/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location / {
        proxy_pass http://app-development-wsgi/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

У меня есть asgi.py

import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from django.urls import path

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

application = get_asgi_application()

from cruze_development.middleware import JWTAuthMiddleware
from cruze_development.consumers import ClubFeedConsumer, RideLocationConsumer


application = ProtocolTypeRouter({
    "http": application,
    "websocket": JWTAuthMiddleware(
        URLRouter([
            path('ws/chat/<str:room_name>/', ClubFeedConsumer.as_asgi()),
            path('ws/location/<str:ride_id>/', RideLocationConsumer.as_asgi()),
        ])
    ),
})

wss://mydomain.com/ws/chat/1/

Я пробую и с ws, и с wss

Помоги мне решить эту проблему, парень!

ОБНОВИТЬ:

Проблема была в том, что в моем файле nginx обязательно нужно использовать некоторые прокси-заголовки для websockets.

вот мой обновленный сниппет кода файла nginx

location /ws/ {
        proxy_pass http://app-development-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;
    }

Но теперь я получаю 500 ошибку при тестировании на postman: Ошибка журнала контейнера:

IP:36032 - - [XX:XX:XX] "WSCONNECTING /chat/1/" - -
ERROR    Exception inside application: No route found for path 'chat/1/'.

Мои требования.txt

django-cacheops==7.0.1
django-cors-headers==3.14.0
django-debug-toolbar==4.0.0
django-environ==0.4.5
django-mysql==3.9.0
django-ninja==0.22.2
django-redis==5.3.0
django-simple-history==2.12.0
django-storages==1.10
Django==5.0.4
djangorestframework_simplejwt==5.3.1
djangorestframework==3.14.0
psycopg2-binary==2.9.9
pillow==10.4.0
channels==4.1.0
channels_redis==4.2.0
daphne
drf-yasg==1.21.8
firebase-admin==6.6.0
pytz
gunicorn==23.0.0

ОБНОВЛЕНИЕ 2:

Вторая проблема была связана с nginx, который по-разному относился к /ws/, когда я попробовал ws/ws/ 2 раза, это сработало. Теперь для окончательного решения я удалил ws/ в asgi.py, чтобы не вносить никаких изменений в мой фронтенд.

my final asgi.py

application = ProtocolTypeRouter({
    "http": application,
    "websocket": JWTAuthMiddleware(
        URLRouter([
            path('chat/<str:room_name>/', ClubFeedConsumer.as_asgi()),
            path('location/<str:ride_id>/', RideLocationConsumer.as_asgi()),
        ])
    ),
})

Надеюсь, это поможет, если кто-то сталкивается с той же проблемой даже спустя годы. Хорошего дня :)

Ответ 1:

Проблема была в том, что в моем файле nginx обязательно нужно использовать некоторые прокси-заголовки для websockets.

вот мой обновленный сниппет кода файла nginx

location /ws/ {
        proxy_pass http://app-development-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;
    }

Но теперь я получаю 500 ошибку при тестировании на postman: Container log error:

IP:36032 - - [XX:XX:XX] «WSCONNECTING /chat/1/» - -. ERROR Исключение внутри приложения: Не найден маршрут для пути 'chat/1/'. Мои требования.txt

django-cacheops==7.0.1
django-cors-headers==3.14.0
django-debug-toolbar==4.0.0
django-environ==0.4.5
django-mysql==3.9.0
django-ninja==0.22.2
django-redis==5.3.0
django-simple-history==2.12.0
django-storages==1.10
Django==5.0.4
djangorestframework_simplejwt==5.3.1
djangorestframework==3.14.0
psycopg2-binary==2.9.9
pillow==10.4.0
channels==4.1.0
channels_redis==4.2.0
daphne
drf-yasg==1.21.8
firebase-admin==6.6.0
pytz
gunicorn==23.0.0

Ответ 2:

Вторая проблема была связана с nginx, который по-разному относился к /ws/, когда я попробовал ws/ws/ 2 раза, это сработало. Теперь для окончательного решения я удалил ws/ в asgi.py, чтобы не вносить никаких изменений в мой фронтенд.

my final asgi.py

application = ProtocolTypeRouter({
    "http": application,
    "websocket": JWTAuthMiddleware(
        URLRouter([
            path('chat/<str:room_name>/', ClubFeedConsumer.as_asgi()),
            path('location/<str:ride_id>/', RideLocationConsumer.as_asgi()),
        ])
    ),
})

Надеюсь, это поможет, если кто-то сталкивается с той же проблемой даже спустя годы. Хорошего дня :)

Вернуться на верх